#!/bin/sh
################################################################################
# functions
################################################################################
. /etc/conf

/usr/bin/test "${MM_DEBUG}" = "yes" && set -x

#===============================================================================
# general functions.
#===============================================================================
mm_command_run() {
    local COMMAND=$1

    local LOG_DIR
    local LOG_FILE
    local RETURN

    if [ "x${MM_DEBUG}" = "xyes" ] ; then
        LOG_DIR="/var/log"
        LOG_FILE="/var/log/minimyth.log"
        if [ ! -e "${LOG_FILE}" ] && [ -w "${LOG_DIR}" ] ; then
            /bin/touch "${LOG_FILE}"
            /bin/chmod 0666 "${LOG_FILE}"
        fi
    else
        LOG_DIR="/dev"
        LOG_FILE="/dev/null"
    fi

    RETURN=0
    if [ -w "${LOG_FILE}" ] ; then
        /bin/echo "--- execution start: ${COMMAND}"  >> "${LOG_FILE}" 2>&1
        ${COMMAND}                                   >> "${LOG_FILE}" 2>&1
        RETURN=$?
        /bin/echo "--- execution end  : ${COMMAND}"  >> "${LOG_FILE}" 2>&1
    else
        /bin/echo "--- execution start: ${COMMAND}"                   2>&1
        ${COMMAND}                                                    2>&1
        RETURN=$?
        /bin/echo "--- execution end  : ${COMMAND}"                   2>&1
    fi

    /usr/bin/test ${RETURN} -eq 0
    return
}

#===============================================================================
# minimyth.conf functions.
#===============================================================================
mm_minimyth_conf_include() {
    local REMOTE_FILE=$1

    local LOCAL_FILE

    LOCAL_FILE="/etc/minimyth.d/${REMOTE_FILE}"
    LOCAL_FILE=`/bin/echo "${LOCAL_FILE}" | /bin/sed -e 's%//*%/%g' | /bin/sed -e 's%/$%%'`

    /usr/bin/test ! -e "${LOCAL_FILE}" && mm_confro_get "${REMOTE_FILE}" "${LOCAL_FILE}"
    /usr/bin/test   -e "${LOCAL_FILE}" && . "${LOCAL_FILE}"
}

#===============================================================================
# mm_url_*_get functions.
#===============================================================================
mm_url_get() {
    local URL=$1
    local LOCAL_FILE=$2

    local REMOTE_PROTOCOL
    local REMOTE_SERVER
    local REMOTE_FILE

    REMOTE_PROTOCOL=`/bin/echo "${URL}" | /usr/bin/cut -d? -f1 \
                                        | /usr/bin/cut -d: -f1`
    REMOTE_SERVER=`  /bin/echo "${URL}" | /usr/bin/cut -d? -f1 \
                                        | /bin/sed 's%^[^:]*:%%' \
                                        | /bin/sed 's%^//%%' \
                                        | /bin/sed 's%^[^@]*@%%' \
                                        | /bin/sed 's%/[^/]*%%g'`
    REMOTE_FILE=`    /bin/echo "${URL}" | /usr/bin/cut -d? -f1 \
                                        | /bin/sed 's%^[^:]*:%%' \
                                        | /bin/sed 's%^//[^/]*/%/%'`

    case "${REMOTE_PROTOCOL}" in
        conf|confro|confrw|dist|file|http|hunt|tftp)
            mm_url_${REMOTE_PROTOCOL}_get "${LOCAL_FILE}" "${REMOTE_FILE}" "${REMOTE_SERVER}" || return
            ;;
        cifs|nfs)
            REMOTE_FILE=`/bin/echo "${URL}" | /bin/sed "s%${MM_MINIMYTH_BOOT_URL}%%"`
            mm_url_${REMOTE_PROTOCOL}_get "${LOCAL_FILE}" "${REMOTE_FILE}" "${MM_MINIMYTH_BOOT_URL}" || return
            ;;
        *)
            /usr/bin/logger -s -t minimyth -p "local0.info" "mm_url_get: protocol '${REMOTE_PROTOCOL}' is not supported."
            /bin/false || return
            ;;
    esac

    /bin/true
    return
}

mm_url_conf_get() {
    local LOCAL_FILE=$1
    local REMOTE_FILE=$2

    /usr/bin/logger -s -t minimyth -p "local0.error" \
        "function 'mm_url_conf_get' is no longer supported. use 'mm_url_confro_get' or 'mm_url_confrw_get' instead."

    /bin/false
    return
}

mm_url_confro_get() {
    local LOCAL_FILE=$1
    local REMOTE_FILE=$2

    local HOST_NAME
    local REMOTE_FILE_0
    local REMOTE_FILE_1

    HOST_NAME=`/bin/hostname`

    LOCAL_FILE=`/bin/echo "${LOCAL_FILE}"   | /bin/sed -e 's%//*%/%g' | /bin/sed -e 's%/$%%'`
    REMOTE_FILE=`/bin/echo "${REMOTE_FILE}" | /bin/sed -e 's%//*%/%g' | /bin/sed -e 's%/$%%'`
    REMOTE_FILE=`/bin/echo "${REMOTE_FILE}" | /bin/sed -e 's%^/%%'`
    if [ -n "${HOST_NAME}" ] ; then
        REMOTE_FILE_0="conf/${HOST_NAME}/${REMOTE_FILE}"
    fi
    REMOTE_FILE_1="conf/default/${REMOTE_FILE}"

    /bin/rm -f "${LOCAL_FILE}"
    ( /usr/bin/test "${LOCAL_FILE}" = "/etc/minimyth.d/minimyth.conf" \
          && mm_url_get "${MM_TFTP_BOOT_URL}${REMOTE_FILE_0}" "${LOCAL_FILE}" \
    ) || \
    ( /usr/bin/test -n "${REMOTE_FILE_0}" \
          && mm_url_get "${MM_MINIMYTH_BOOT_URL}${REMOTE_FILE_0}" "${LOCAL_FILE}" \
    ) || \
    ( /usr/bin/test -n "${REMOTE_FILE_1}" \
          && mm_url_get "${MM_MINIMYTH_BOOT_URL}${REMOTE_FILE_1}" "${LOCAL_FILE}" \
    ) || \
    return

    return
}

mm_url_confrw_get() {
    local LOCAL_FILE=$1
    local REMOTE_FILE=$2

    local HOST_NAME
    local REMOTE_FILE_0

    HOST_NAME=`/bin/hostname`

    LOCAL_FILE=`/bin/echo "${LOCAL_FILE}"   | /bin/sed -e 's%//*%/%g' | /bin/sed -e 's%/$%%'`
    REMOTE_FILE=`/bin/echo "${REMOTE_FILE}" | /bin/sed -e 's%//*%/%g' | /bin/sed -e 's%/$%%'`
    REMOTE_FILE=`/bin/echo "${REMOTE_FILE}" | /bin/sed -e 's%^/%%'`
    if [ -n "${HOST_NAME}" ] ; then
        REMOTE_FILE_0=`/bin/echo ${REMOTE_FILE}`
        REMOTE_FILE_0="conf-rw/${HOST_NAME}/${REMOTE_FILE_0}"
    fi

    /bin/rm -f "${LOCAL_FILE}"
    ( /usr/bin/test -n "${REMOTE_FILE_0}" \
          && mm_url_get "${MM_MINIMYTH_BOOT_URL}${REMOTE_FILE_0}" "${LOCAL_FILE}" \
    ) || \
    return

    return
}

mm_url_dist_get() {
    local LOCAL_FILE=$1
    local REMOTE_FILE=$2

    local REMOTE_FILE_0

    LOCAL_FILE=`/bin/echo "${LOCAL_FILE}"   | /bin/sed -e 's%//*%/%g' | /bin/sed -e 's%/$%%'`
    REMOTE_FILE=`/bin/echo "${REMOTE_FILE}" | /bin/sed -e 's%//*%/%g' | /bin/sed -e 's%/$%%'`
    REMOTE_FILE=`/bin/echo "${REMOTE_FILE}" | /bin/sed -e 's%^/%%'`
    if [ -n "${MM_ROOTFS_IMAGE}" ] ; then
        REMOTE_FILE_0=`/bin/echo ${MM_ROOTFS_IMAGE} | /bin/sed -e 's%//*%/%g' | /bin/sed -e 's%[^/]*$%%' | /bin/sed -e 's%/$%%'`
        REMOTE_FILE_0="${REMOTE_FILE_0}/${REMOTE_FILE}"
    else
        REMOTE_FILE_0="/minimyth-${MM_VERSION}/${REMOTE_FILE}"
    fi

    /bin/rm -f "${LOCAL_FILE}"
    ( /usr/bin/test -n "${REMOTE_FILE_0}" \
          && mm_url_get "${MM_MINIMYTH_BOOT_URL}${REMOTE_FILE_0}" "${LOCAL_FILE}" \
    ) || \
    return

    return
}

mm_url_file_get() {
    local LOCAL_FILE=$1
    local REMOTE_FILE=$2

    local LOCAL_DIR

    LOCAL_FILE=`/bin/echo "${LOCAL_FILE}"   | /bin/sed -e 's%//*%/%g' | /bin/sed -e 's%/$%%'`
    REMOTE_FILE=`/bin/echo "${REMOTE_FILE}" | /bin/sed -e 's%//*%/%g' | /bin/sed -e 's%/$%%'`

    LOCAL_DIR=`/bin/echo "${LOCAL_FILE}" | /bin/sed -e 's%[^/]*$%%' -e 's%/$%%'`
    /usr/bin/test -n "${LOCAL_DIR}" && /bin/mkdir -p "${LOCAL_DIR}"
    /usr/bin/test -n "${LOCAL_DIR}" && /usr/bin/test ! -d "${LOCAL_DIR}" && return

    /bin/cp -f "${REMOTE_FILE}" "${LOCAL_FILE}" || return

    /usr/bin/logger -s -t minimyth -p "local0.info" "'file:${REMOTE_FILE}' downloaded."

    return
}

mm_url_http_get() {
    local LOCAL_FILE=$1
    local REMOTE_FILE=$2
    local REMOTE_SERVER=$3

    local LOCAL_DIR

    LOCAL_FILE=`/bin/echo "${LOCAL_FILE}"   | /bin/sed -e 's%//*%/%g' | /bin/sed -e 's%/$%%'`
    REMOTE_FILE=`/bin/echo "${REMOTE_FILE}" | /bin/sed -e 's%//*%/%g' | /bin/sed -e 's%/$%%'`
    REMOTE_FILE=`/bin/echo "${REMOTE_FILE}" | /bin/sed -e 's%^/%%'`
    REMOTE_FILE="/${REMOTE_FILE}"

    LOCAL_DIR=`/bin/echo "${LOCAL_FILE}" | /bin/sed -e 's%[^/]*$%%' -e 's%/$%%'`
    /usr/bin/test -n "${LOCAL_DIR}" && /bin/mkdir -p "${LOCAL_DIR}"
    /usr/bin/test -n "${LOCAL_DIR}" && /usr/bin/test ! -d "${LOCAL_DIR}" && return

    /usr/bin/curl -s -f "http://${REMOTE_SERVER}${REMOTE_FILE}" -o "${LOCAL_FILE}" || return

    /usr/bin/logger -s -t minimyth -p "local0.info" "'http://${REMOTE_SERVER}${REMOTE_FILE}' downloaded."

    return
}

mm_url_hunt_get() {
    local LOCAL_FILE=$1
    local REMOTE_FILE=$2

    mm_url_dist_get   "${LOCAL_FILE}" "${REMOTE_FILE}" || \
    mm_url_confro_get "${LOCAL_FILE}" "${REMOTE_FILE}" || \
    return

    return
}

mm_url_tftp_get() {
    local LOCAL_FILE=$1
    local REMOTE_FILE=$2
    local REMOTE_SERVER=$3

    local LOCAL_DIR

    LOCAL_FILE=`/bin/echo "${LOCAL_FILE}"   | /bin/sed -e 's%//*%/%g' | /bin/sed -e 's%/$%%'`
    REMOTE_FILE=`/bin/echo "${REMOTE_FILE}" | /bin/sed -e 's%//*%/%g' | /bin/sed -e 's%/$%%'`
    REMOTE_FILE=`/bin/echo "${REMOTE_FILE}" | /bin/sed -e 's%^/%%'`
    REMOTE_FILE="/${REMOTE_FILE}"

    LOCAL_DIR=`/bin/echo "${LOCAL_FILE}" | /bin/sed -e 's%[^/]*$%%' -e 's%/$%%'`
    /usr/bin/test -n "${LOCAL_DIR}" && /bin/mkdir -p "${LOCAL_DIR}"
    /usr/bin/test -n "${LOCAL_DIR}" && /usr/bin/test ! -d "${LOCAL_DIR}" && return

    /usr/bin/tftp -g -r "${REMOTE_FILE}" -l "${LOCAL_FILE}" "${REMOTE_SERVER}" || return

    /usr/bin/logger -s -t minimyth -p "local0.info" "'tftp://${REMOTE_SERVER}${REMOTE_FILE}' downloaded."

    return
}

mm_url_cifs_get() {
    local LOCAL_FILE=$1
    local REMOTE_FILE=$2
    local REMOTE_SERVER=$3

    local LOCAL_DIR

    LOCAL_FILE=`/bin/echo "${LOCAL_FILE}"   | /bin/sed -e 's%//*%/%g' | /bin/sed -e 's%/$%%'`
    REMOTE_FILE=`/bin/echo "${REMOTE_FILE}" | /bin/sed -e 's%//*%/%g' | /bin/sed -e 's%/$%%'`
    REMOTE_FILE=`/bin/echo "${REMOTE_FILE}" | /bin/sed -e 's%^/%%'`
    REMOTE_FILE="/${REMOTE_FILE}"

    LOCAL_DIR=`/bin/echo "${LOCAL_FILE}" | /bin/sed -e 's%[^/]*$%%' -e 's%/$%%'`
    /usr/bin/test -n "${LOCAL_DIR}" && /bin/mkdir -p "${LOCAL_DIR}"
    /usr/bin/test -n "${LOCAL_DIR}" && /usr/bin/test ! -d "${LOCAL_DIR}" && return

    if [ ! -f "/var/lib/minimyth.bootdir.cifs_mounted" ] ; then
        /usr/bin/logger -s -t minimyth -p "local0.info" "Mounting '${REMOTE_SERVER}' share for conf and conf-ro operations"
        mm_url_mount "${REMOTE_SERVER}" "/var/minimyth.bootdir" || return
        /bin/touch "/var/lib/minimyth.bootdir.cifs_mounted"
    fi

    /bin/cp "/var/minimyth.bootdir/${REMOTE_FILE}" "${LOCAL_FILE}" || return

    /usr/bin/logger -s -t minimyth -p "local0.info" "File '${REMOTE_SERVER}${REMOTE_FILE}' downloaded."

    return
}

mm_url_nfs_get() {
    local LOCAL_FILE=$1
    local REMOTE_FILE=$2
    local REMOTE_SERVER=$3

    local LOCAL_DIR

    LOCAL_FILE=`/bin/echo "${LOCAL_FILE}"   | /bin/sed -e 's%//*%/%g' | /bin/sed -e 's%/$%%'`
    REMOTE_FILE=`/bin/echo "${REMOTE_FILE}" | /bin/sed -e 's%//*%/%g' | /bin/sed -e 's%/$%%'`
    REMOTE_FILE=`/bin/echo "${REMOTE_FILE}" | /bin/sed -e 's%^/%%'`
    REMOTE_FILE="/${REMOTE_FILE}"

    LOCAL_DIR=`/bin/echo "${LOCAL_FILE}" | /bin/sed -e 's%[^/]*$%%' -e 's%/$%%'`
    /usr/bin/test -n "${LOCAL_DIR}" && /bin/mkdir -p "${LOCAL_DIR}"
    /usr/bin/test -n "${LOCAL_DIR}" && /usr/bin/test ! -d "${LOCAL_DIR}" && return

    if [ ! -f "/var/lib/minimyth.bootdir.nfs_mounted" ] ; then
        /usr/bin/logger -s -t minimyth -p "local0.info" "Mounting '${REMOTE_SERVER}' share for conf and conf-ro operations"
        mm_url_mount "${REMOTE_SERVER}" "/var/minimyth.bootdir/" || return
        /bin/touch "/var/lib/minimyth.bootdir.nfs_mounted"
    fi

    /bin/cp "/var/minimyth.bootdir/${REMOTE_FILE}" "${LOCAL_FILE}" || return

    /usr/bin/logger -s -t minimyth -p "local0.info" "File '${REMOTE_SERVER}${REMOTE_FILE}' downloaded."

    return
}

#===============================================================================
# mm_url_*_put functions.
#===============================================================================
mm_url_put() {
    local URL=$1
    local LOCAL_FILE=$2

    local REMOTE_PROTOCOL
    local REMOTE_SERVER
    local REMOTE_FILE

    REMOTE_PROTOCOL=`/bin/echo "${URL}" | /usr/bin/cut -d? -f1 \
                                        | /usr/bin/cut -d: -f1`
    REMOTE_SERVER=`  /bin/echo "${URL}" | /usr/bin/cut -d? -f1 \
                                        | /bin/sed 's%^[^:]*:%%' \
                                        | /bin/sed 's%^//%%' \
                                        | /bin/sed 's%^[^@]*@%%' \
                                        | /bin/sed 's%/[^/]*%%g'`
    REMOTE_FILE=`    /bin/echo "${URL}" | /usr/bin/cut -d? -f1 \
                                        | /bin/sed 's%^[^:]*:%%' \
                                        | /bin/sed 's%^//[^/]*/%/%'`

    case "${REMOTE_PROTOCOL}" in
        conf|confrw|file|http|tftp)
            mm_url_${REMOTE_PROTOCOL}_put "${LOCAL_FILE}" "${REMOTE_FILE}" "${REMOTE_SERVER}" || return
            ;;
        cifs|nfs)
            REMOTE_FILE=`/bin/echo "${URL}" | /bin/sed "s%${MM_MINIMYTH_BOOT_URL}%%"`
            mm_url_${REMOTE_PROTOCOL}_put "${LOCAL_FILE}" "${REMOTE_FILE}" "${MM_MINIMYTH_BOOT_URL}" || return
            ;;
        *)
            /usr/bin/logger -s -t minimyth -p "local0.info" "mm_url_put: protocol '${REMOTE_PROTOCOL}' is not supported."
            /bin/false || return
            ;;
    esac

    /bin/true
    return
}

mm_url_conf_put() {
    local LOCAL_FILE=$1
    local REMOTE_FILE=$2

    /usr/bin/logger -s -t minimyth -p "local0.error" \
        "function 'mm_url_conf_put' is no longer supported. use 'mm_url_confrw_put' instead."

    /bin/false
    return
}

mm_url_confrw_put() {
    local LOCAL_FILE=$1
    local REMOTE_FILE=$2

    local HOST_NAME
    local REMOTE_FILE_0

    HOST_NAME=`/bin/hostname`

    if [ ! -f "${LOCAL_FILE}" ] ; then
        /usr/bin/logger -s -t minimyth -p "local0.error"  \
            "cannot post conf file '${LOCAL_FILE}' because file not found."
        /bin/false
        return
    fi
    if [ -z "${HOST_NAME}" ] ; then
        /usr/bin/logger -s -t minimyth -p "local0.error"  \
            "cannot post conf file '${LOCAL_FILE}' because hostname is unknown."
        /bin/false
        return
    fi

    LOCAL_FILE=`/bin/echo "${LOCAL_FILE}"   | /bin/sed -e 's%//*%/%g' | /bin/sed -e 's%/$%%'`
    REMOTE_FILE=`/bin/echo "${REMOTE_FILE}" | /bin/sed -e 's%//*%/%g' | /bin/sed -e 's%/$%%'`
    REMOTE_FILE=`/bin/echo "${REMOTE_FILE}" | /bin/sed -e 's%^/%%'`
    if [ -n "${HOST_NAME}" ] ; then
        REMOTE_FILE_0=`/bin/echo ${REMOTE_FILE}`
        REMOTE_FILE_0="conf-rw/${HOST_NAME}/${REMOTE_FILE_0}"
    fi

    ( /usr/bin/test -n "${REMOTE_FILE_0}" \
          && mm_url_put "${MM_MINIMYTH_BOOT_URL}${REMOTE_FILE_0}" "${LOCAL_FILE}" \
          && ( /usr/bin/logger -s -t minimyth -p "local0.info" "'${MM_MINIMYTH_BOOT_URL}${REMOTE_FILE_0}' uploaded." \
                   || /bin/true \
             ) \
    ) || \
    return

    return
}

mm_url_file_put() {
    local LOCAL_FILE=$1
    local REMOTE_FILE=$2

    local REMOTE_DIR

    LOCAL_FILE=`/bin/echo "${LOCAL_FILE}"   | /bin/sed -e 's%//*%/%g'`
    REMOTE_FILE=`/bin/echo "${REMOTE_FILE}" | /bin/sed -e 's%//*%/%g'`

    if [ ! -f "${LOCAL_FILE}" ] ; then
        /usr/bin/logger -s -t minimyth -p "local0.error"  \
            "cannot post conf file '${LOCAL_FILE}' because file not found."
        /bin/false
        return
    fi

    REMOTE_DIR=`/bin/echo "${REMOTE_FILE}" | /bin/sed -e 's%[^/]*$%%' -e 's%/$%%'`
    /usr/bin/test -n "${REMOTE_DIR}" && /bin/mkdir -p "${REMOTE_DIR}"
    /usr/bin/test -n "${REMOTE_DIR}" && /usr/bin/test ! -d "${REMOTE_DIR}" && return

    if /bin/cp -f "${LOCAL_FILE}" "${REMOTE_FILE}" ; then
        /usr/bin/logger -s -t minimyth -p "local0.info"  \
            "'file:${REMOTE_FILE}' posted."
        /bin/true
        return
    else
        /usr/bin/logger -s -t minimyth -p "local0.error" \
            "'file:${REMOTE_FILE}' failed to post."
        /bin/false
        return
    fi

    return
}

mm_url_http_put() {
    local LOCAL_FILE=$1
    local REMOTE_FILE=$2
    local REMOTE_SERVER=$3

    LOCAL_FILE=`/bin/echo "${LOCAL_FILE}"   | /bin/sed -e 's%//*%/%g'`
    REMOTE_FILE=`/bin/echo "${REMOTE_FILE}" | /bin/sed -e 's%//*%/%g' | /bin/sed -e 's%^/%%'`
    REMOTE_FILE="/${REMOTE_FILE}"

    if [ ! -f "${LOCAL_FILE}" ] ; then
        /usr/bin/logger -s -t minimyth -p "local0.error"  \
            "[functions/mm_url_http_put] cannot post conf file '${LOCAL_FILE}' because file not found."
        /bin/false
        return
    fi

    if /usr/bin/curl -s -f -T "${LOCAL_FILE}" "http://${REMOTE_SERVER}${REMOTE_FILE}" ; then
        /usr/bin/logger -s -t minimyth -p "local0.info"  \
            "[functions/mm_url_http_put] 'http://${REMOTE_SERVER}${REMOTE_FILE}' posted."
        /bin/true
        return
    else
        /usr/bin/logger -s -t minimyth -p "local0.error" \
            "[functions/mm_url_http_put] 'http://${REMOTE_SERVER}${REMOTE_FILE}' failed to post. Will retry with verbose. For output, look on /var/log/minimyth.err"
            /usr/bin/curl -v -S -T "${LOCAL_FILE}" "http://${REMOTE_SERVER}${REMOTE_FILE}" > /var/log/minimyth.err 2>&1
        /bin/false
        return
    fi

    return
}

mm_url_tftp_put() {
    local LOCAL_FILE=$1
    local REMOTE_FILE=$2
    local REMOTE_SERVER=$3

    LOCAL_FILE=`/bin/echo "${LOCAL_FILE}"   | /bin/sed -e 's%//*%/%g'`
    REMOTE_FILE=`/bin/echo "${REMOTE_FILE}" | /bin/sed -e 's%//*%/%g' | /bin/sed -e 's%^/%%'`
    REMOTE_FILE="/${REMOTE_FILE}"

    if [ ! -f "${LOCAL_FILE}" ] ; then
        /usr/bin/logger -s -t minimyth -p "local0.error"  \
            "cannot post conf file '${LOCAL_FILE}' because file not found."
        /bin/false
        return
    fi

    if /usr/bin/tftp -p -l "${LOCAL_FILE}" -r "${REMOTE_FILE}" "${REMOTE_SERVER}" ; then
        /usr/bin/logger -s -t minimyth -p "local0.info"  \
            "'tftp://${REMOTE_SERVER}${REMOTE_FILE}' posted."
        /bin/true
        return
    else
        /usr/bin/logger -s -t minimyth -p "local0.error" \
            "'tftp://${REMOTE_SERVER}${REMOTE_FILE}' failed to post."
        /bin/false
        return
    fi

    return
}

mm_url_cifs_put() {
    local LOCAL_FILE=$1
    local REMOTE_FILE=$2
    local REMOTE_SERVER=$3

    LOCAL_FILE=`/bin/echo "${LOCAL_FILE}"   | /bin/sed -e 's%//*%/%g'`
    REMOTE_FILE=`/bin/echo "${REMOTE_FILE}" | /bin/sed -e 's%//*%/%g' | /bin/sed -e 's%^/%%'`
    REMOTE_FILE="/${REMOTE_FILE}"

    if [ ! -f "${LOCAL_FILE}" ] ; then
        /usr/bin/logger -s -t minimyth -p "local0.error"  \
            "cannot post conf file '${LOCAL_FILE}' because file not found."
        /bin/false
        return
    fi

    if [ ! -f "/var/lib/minimyth.bootdir.cifs_mounted" ] ; then
        /usr/bin/logger -s -t minimyth -p "local0.info" "Mounting '${REMOTE_SERVER}' share for conf and conf-ro operation"
        mm_url_mount "${REMOTE_SERVER}" "/var/minimyth.bootdir" || return
        /bin/touch "/var/lib/minimyth.bootdir.cifs_mounted"
    fi

    /bin/cp "${LOCAL_FILE}" "/var/minimyth.bootdir/${REMOTE_FILE}"

    /usr/bin/logger -s -t minimyth -p "local0.info"  \
            "File ${LOCAL_FILE} posted to '${REMOTE_SERVER}${REMOTE_FILE}'."

    return
}

mm_url_nfs_put() {
    local LOCAL_FILE=$1
    local REMOTE_FILE=$2
    local REMOTE_SERVER=$3

    LOCAL_FILE=`/bin/echo "${LOCAL_FILE}"   | /bin/sed -e 's%//*%/%g'`
    REMOTE_FILE=`/bin/echo "${REMOTE_FILE}" | /bin/sed -e 's%//*%/%g' | /bin/sed -e 's%^/%%'`
    REMOTE_FILE="/${REMOTE_FILE}"

    if [ ! -f "${LOCAL_FILE}" ] ; then
        /usr/bin/logger -s -t minimyth -p "local0.error"  \
            "cannot post conf file '${LOCAL_FILE}' because file not found."
        /bin/false
        return
    fi

    if [ ! -f "/var/lib/minimyth.bootdir.nfs_mounted" ] ; then
        /usr/bin/logger -s -t minimyth -p "local0.info" "Mounting '${REMOTE_SERVER}' share for conf and conf-ro operation"
        mm_url_mount "${REMOTE_SERVER}" "/var/minimyth.bootdir/" || return
        /bin/touch "/var/lib/minimyth.bootdir.nfs_mounted"
    fi

    /bin/cp "${LOCAL_FILE}" "/var/minimyth.bootdir/${REMOTE_FILE}"

    /usr/bin/logger -s -t minimyth -p "local0.info"  \
            "File ${LOCAL_FILE} posted to '${REMOTE_SERVER}${REMOTE_FILE}'."

    return
}

#===============================================================================
# mm_confro_* and mm_confrw_* functions.
#===============================================================================
mm_conf_get() {
    local REMOTE_FILE=$1
    local LOCAL_FILE=$2

    /usr/bin/logger -s -t minimyth -p "local0.error" \
        "function 'mm_conf_get' is no longer supported. use 'mm_confro_get' or 'mm_confrw_get' instead."

    /bin/false
    return
}

mm_confro_get() {
    local REMOTE_FILE=$1
    local LOCAL_FILE=$2

    mm_url_confro_get "${LOCAL_FILE}" "${REMOTE_FILE}" || return

    return
}

mm_confrw_get() {
    local REMOTE_FILE=$1
    local LOCAL_FILE=$2

    mm_url_confrw_get "${LOCAL_FILE}" "${REMOTE_FILE}" || return

    return
}

mm_conf_put() {
    local REMOTE_FILE=$1
    local LOCAL_FILE=$2

    /usr/bin/logger -s -t minimyth -p "local0.error" \
        "function 'mm_conf_put' is no longer supported. use 'mm_confrw_put' instead."

    /bin/false
    return
}

mm_confrw_put() {
    local REMOTE_FILE=$1
    local LOCAL_FILE=$2

    mm_url_confrw_put "${LOCAL_FILE}" "${REMOTE_FILE}" || return

    return
}

#===============================================================================
#
#===============================================================================
mm_game_restore() {

    local FILE
    local REMOTE_FILE
    local LOCAL_DIR
    local LOCAL_FILE

    FILE="game.tar"
    REMOTE_FILE="${FILE}"
    LOCAL_DIR="${HOME}/tmp"
    LOCAL_FILE="${LOCAL_DIR}/${FILE}"

    /usr/bin/test -n "${LOCAL_DIR}" && /bin/mkdir -p "${LOCAL_DIR}"
    /usr/bin/test -n "${LOCAL_DIR}" && /usr/bin/test ! -d "${LOCAL_DIR}" && return

    /bin/rm -f "${LOCAL_FILE}"

    mm_confrw_get "${REMOTE_FILE}" "${LOCAL_FILE}"

    if [ -n "${LOCAL_FILE}" ] ; then
        cd /home/minimyth
        /bin/tar -xf "${LOCAL_FILE}"
        /bin/rm -f "${LOCAL_FILE}"
    fi

    /bin/rm -f "${LOCAL_FILE}"
}

mm_game_save() {

    local FILE
    local REMOTE_FILE
    local LOCAL_DIR
    local LOCAL_FILE

    FILE="game.tar"
    REMOTE_FILE="${FILE}"
    LOCAL_DIR="${HOME}/tmp"
    LOCAL_FILE="${LOCAL_DIR}/${FILE}"

    /usr/bin/test -n "${LOCAL_DIR}" && /bin/mkdir -p "${LOCAL_DIR}"
    /usr/bin/test -n "${LOCAL_DIR}" && /usr/bin/test ! -d "${LOCAL_DIR}" && return

    # Enumerate all the files to be saved.
    local IFS_SAVE
    local GAME_SAVE_FULL
    local GAME_SAVE_LIST
    local GAME_SAVE_ITEM
    local GAME_SAVE
    GAME_SAVE_FULL=`/bin/echo ":${MM_GAME_SAVE_LIST}" \
        | /bin/sed -e 's%:%:/home/minimyth/%g'        \
        | /bin/sed -e 's%^:%%'`
    IFS_SAVE=${IFS}
    IFS=:
    for GAME_SAVE_ITEM in ${GAME_SAVE_FULL}; do
        if [ -e "${GAME_SAVE_ITEM}" ] ; then
            GAME_SAVE=`/bin/echo "${GAME_SAVE_ITEM}" \
                | /bin/sed -e 's%^/home/minimyth/%%'`
            GAME_SAVE_LIST="${GAME_SAVE_LIST}|${GAME_SAVE}"
        fi
    done
    IFS=${IFS_SAVE}
    GAME_SAVE_LIST=`/bin/echo ${GAME_SAVE_LIST} \
        | /bin/sed -e 's%^|%%'                  \
        | /bin/sed -e 's%|%:%g'`

    /bin/rm -f "${LOCAL_FILE}"
    if [ -n "${GAME_SAVE_LIST}" ] ; then
        /bin/mkdir -p /home/minimyth
        cd /home/minimyth
        local IFS_SAVE
        IFS_SAVE=${IFS}
        IFS=:${IFS}
        /bin/tar -cf "${LOCAL_FILE}" ${GAME_SAVE_LIST} || /bin/rm -f "${LOCAL_FILE}"
        IFS=${IFS_SAVE}
        if [ ! -e "${LOCAL_FILE}" ] ; then
            /usr/bin/logger -s -t minimyth -p "local0.error" \
                "failed to create game files tarball."
            /bin/false
            return
        fi
        mm_confrw_put "${REMOTE_FILE}" "${LOCAL_FILE}"
        if [ $? -ne 0 ] ; then
            /bin/rm -f "${LOCAL_FILE}"
            /bin/false
            return
        else
            /bin/rm -f "${LOCAL_FILE}"
        fi
    fi
}

mm_codecs_fetch_and_save() {

    local FILE
    local REMOTE_FILE
    local LOCAL_DIR
    local LOCAL_FILE

    local CODECS_BASE
    local CODECS_FILE
    local CODECS_URL

    FILE="codecs.sfs"
    REMOTE_FILE="${FILE}"
    LOCAL_DIR="${HOME}/tmp"
    LOCAL_FILE="${LOCAL_DIR}/${FILE}"

    /usr/bin/test -n "${LOCAL_DIR}" && /bin/mkdir -p "${LOCAL_DIR}"
    /usr/bin/test -n "${LOCAL_DIR}" && /usr/bin/test ! -d "${LOCAL_DIR}" && return

    CODECS_BASE="essential-20061022"
    CODECS_FILE="${CODECS_BASE}.tar.bz2"
    CODECS_URL="http://www.mplayerhq.hu/MPlayer/releases/codecs/${CODECS_FILE}"
    /bin/rm -rf "${LOCAL_DIR}/${CODECS_BASE}"
    /bin/rm -f "${LOCAL_DIR}/${CODECS_FILE}"
    cd "${LOCAL_DIR}"
    mm_url_get "${CODECS_URL}" "${CODECS_FILE}"
    if [ $? -ne 0 ] ; then
        /usr/bin/logger -s -t minimyth -p "local0.error" \
            "failed to create the codecs file because no codecs were downloaded."
        cd "${HOME}"
        /bin/rm -rf "${LOCAL_DIR}/${CODECS_BASE}"
        /bin/rm -f "${LOCAL_DIR}/${CODECS_FILE}"
        /bin/false
        return
    fi
    /bin/tar -jxf "${CODECS_FILE}"
    /bin/rm -f "${CODECS_FILE}"

    if [ ! -d "${LOCAL_DIR}/${CODECS_BASE}" ] || [ `/bin/ls -1 "${LOCAL_DIR}/${CODECS_BASE}" | /usr/bin/wc -l` -eq 0 ] ; then
        /usr/bin/logger -s -t minimyth -p "local0.error" \
            "failed to create the codecs file because downloaded codecs file was empty."
        cd "${HOME}"
        /bin/rm -rf "${LOCAL_DIR}/${CODECS_BASE}"
        /bin/false
        return
    fi

    cd "${LOCAL_DIR}"
    /bin/chown `/usr/bin/id -u`:`/usr/bin/id -g` ${LOCAL_DIR}/${CODECS_BASE}
    /bin/chmod 0755                              ${LOCAL_DIR}/${CODECS_BASE}
    /bin/chown `/usr/bin/id -u`:`/usr/bin/id -g` ${LOCAL_DIR}/${CODECS_BASE}/*
    /bin/chmod 0644                              ${LOCAL_DIR}/${CODECS_BASE}/*

    /bin/rm -f "${LOCAL_FILE}"
    /usr/bin/fakeroot /usr/bin/mksquashfs "${LOCAL_DIR}/${CODECS_BASE}" ${LOCAL_FILE} > /dev/null 2>&1
    if [ $? -ne 0 ] ; then
        cd "${HOME}"
        /bin/rm -rf "${LOCAL_DIR}/${CODECS_BASE}"
        /bin/rm -f ${LOCAL_FILE}
        /usr/bin/logger -s -t minimyth -p "local0.error" \
            "failed to create the codecs file because squashfs failed."
        /bin/false
        return
    fi

    mm_confrw_put "${REMOTE_FILE}" "${LOCAL_FILE}"
    if [ $? -ne 0 ] ; then
        cd "${HOME}"
        /bin/rm -rf "${LOCAL_DIR}/${CODECS_BASE}"
        /bin/rm -f ${LOCAL_FILE}
        /usr/bin/logger -s -t minimyth -p "local0.error" \
            "failed to save the codecs file."
        /bin/false
        return
    fi

    cd "${HOME}"
    /bin/rm -rf "${LOCAL_DIR}/${CODECS_BASE}"
    /bin/rm -f "${LOCAL_FILE}"
    /bin/true
}

mm_extras_save() {

    if [ ! -d /usr/local ] ; then
        /usr/bin/logger -s -t minimyth -p "local0.error" \
            "failed to create the extras file because the extras directory does not exist."
        /bin/false
        return
    fi
    if [ `/bin/ls -1 /usr/local | /usr/bin/wc -l` -eq 0 ] ; then
        /usr/bin/logger -s -t minimyth -p "local0.error" \
            "failed to create the extras file because the extras directory is empty."
        /bin/false
        return
    fi

    local FILE
    local REMOTE_FILE
    local LOCAL_DIR
    local LOCAL_FILE

    FILE="extras.sfs"
    REMOTE_FILE="${FILE}"
    LOCAL_DIR="${HOME}/tmp"
    LOCAL_FILE="${LOCAL_DIR}/${FILE}"

    /bin/rm -f "${LOCAL_FILE}"
    /bin/mkdir -p "${LOCAL_DIR}"
    /usr/bin/mksquashfs /usr/local ${LOCAL_FILE} > /dev/null 2>&1
    if [ $? -ne 0 ] ; then
        /bin/rm -f ${LOCAL_FILE}
        /usr/bin/logger -s -t minimyth -p "local0.error" \
            "failed to create the extras file because squashfs failed."
        /bin/false
        return
    fi

    mm_confrw_put "${REMOTE_FILE}" "${LOCAL_FILE}"
    if [ $? -ne 0 ] ; then
        /bin/rm -f ${LOCAL_FILE}
        /usr/bin/logger -s -t minimyth -p "local0.error" \
            "failed to save the extras file."
        /bin/false
        return
    fi

    /bin/rm -f "${LOCAL_FILE}"
    /bin/true
}

mm_themecache_save() {

    if [ ! -d /home/minimyth/.mythtv/cache/themecache ] ; then
        /usr/bin/logger -s -t minimyth -p "local0.error" \
            "[functions/mm_themecache_save] failed to create the MythTV themecache file because the MythTV themecache directory does not exist!"
        /bin/false
        return
    fi
    if [ -z "`cd /home/minimyth/.mythtv/cache/themecache ; /bin/ls -A`" ] ; then
        /usr/bin/logger -s -t minimyth -p "local0.error" \
            "[functions/mm_themecache_save] failed to create the MythTV themecache file because the MythTV themecache directory seems to be empty!"
        /bin/false
        return
    fi

    local FILE
    local REMOTE_FILE
    local LOCAL_DIR
    local LOCAL_FILE

    # FILE=`cd /home/minimyth/.mythtv/cache/themecache ; /bin/ls`.sfs
    FILE="themecache.sfs"
    REMOTE_FILE="${FILE}"
    LOCAL_DIR="${HOME}/tmp"
    LOCAL_FILE="${LOCAL_DIR}/${FILE}"

    /bin/rm -f "${LOCAL_FILE}"
    /bin/mkdir -p "${LOCAL_DIR}"
    /usr/bin/mksquashfs /home/minimyth/.mythtv/cache/themecache ${LOCAL_FILE} > /dev/null 2>&1
    if [ $? -ne 0 ] ; then
        /bin/rm -f ${LOCAL_FILE}
        /usr/bin/logger -s -t minimyth -p "local0.error" \
            "[functions/mm_themecache_save] failed to create the MythTV themecache file because squashfs failed."
        /bin/false
        return
    fi

    /usr/bin/logger -t minimyth -p "local0.info" "[functions/mm_themecache_save] themecache ${LOCAL_FILE} successfuly prepared..."

    mm_confrw_put "${REMOTE_FILE}" "${LOCAL_FILE}"
    if [ $? -ne 0 ] ; then
        /bin/rm -f ${LOCAL_FILE}
        /usr/bin/logger -s -t minimyth -p "local0.error" \
            "[functions/mm_themecache_save] failed to upload the MythTV themecache file!"
        /bin/false
        return
    fi

    /bin/rm -f "${LOCAL_FILE}"
    /bin/true
}

mm_cookiejar_save() {

    if [ -e /home/minimyth/.mythtv/MythBrowser/cookiejar.txt ] ; then
        mm_confrw_put "mythbrowser_cookiejar.txt" "/home/minimyth/.mythtv/MythBrowser/cookiejar.txt"
        if [ $? -ne 0 ] ; then
            /usr/bin/logger -s -t minimyth -p "local0.error" \
                "[functions/mm_cookiejar_save] failed to upload the MythBrowser cookiejar.txt file!"
            /bin/false
            return
        fi
    fi

    if [ -d /home/minimyth/.config ] ; then
        cd /home/minimyth
        tar -jcvvf /tmp/google-chrome-config.tar.bz2 ./.config*
        mm_confrw_put "google-chrome-config.tar.bz2" "/tmp/google-chrome-config.tar.bz2"
        rm -f /tmp/google-chrome-config.tar.bz2
        if [ $? -ne 0 ] ; then
            /usr/bin/logger -s -t minimyth -p "local0.error" \
                "[functions/mm_cookiejar_save] failed to upload the google-chrome-config.tar.bz2 file!"
            /bin/false
            return
        fi
    fi

    if [ -d /home/minimyth/.mozilla ] ; then
        cd /home/minimyth
        tar -jcvvf /tmp/mozilla-firefox-config.tar.bz2 ./.mozilla*
        mm_confrw_put "mozilla-firefox-config.tar.bz2" "/tmp/mozilla-firefox-config.tar.bz2"
        rm -f /tmp/mozilla-firefox-config.tar.bz2
        if [ $? -ne 0 ] ; then
            /usr/bin/logger -s -t minimyth -p "local0.error" \
                "[functions/mm_cookiejar_save] failed to upload the mozilla-firefox-config.tar.bz2 file!"
            /bin/false
            return
        fi
    fi

    /usr/bin/logger -s -t minimyth -p "local0.error" \
        "[functions/mm_cookiejar_save] MythBrowser cookiejar.txt file and Chrome/Mozilla configs uploaded sucessfuly..."
    /bin/true
    return
}

mm_message_output() {
    local LEVEL=$1
    local MESSAGE=$2

    if [ `mm_splash_running_test ; /bin/echo $?` -eq 0 ] ; then
        # /usr/bin/logger    -t minimyth -p "local0.${LEVEL}" "${MESSAGE}"
        mm_splash_message_output "${MESSAGE}"
    else
        /usr/bin/logger -s -t minimyth -p "local0.${LEVEL}" "${MESSAGE}"
    fi

    if [ "x${LEVEL}" = "xerr"  ] ; then
        /bin/mkdir -p /var/log
        /bin/touch    /var/log/minimyth.err.log
        if [ -w /var/log/minimyth.err.log ] ; then
            /bin/echo -E "${MESSAGE}" >> /var/log/minimyth.err.log
            /bin/chmod 0666 /var/log/minimyth.err.log
        fi
        mm_splash_command "log ${MESSAGE}"
    fi
    if [ "x${LEVEL}" = "xwarn" ] ; then
        /bin/mkdir -p /var/log
        /bin/touch    /var/log/minimyth.warn.log
        if [ -w /var/log/minimyth.warn.log ] ; then
            /bin/echo -E "${MESSAGE}" >> /var/log/minimyth.warn.log
            /bin/chmod 0666 /var/log/minimyth.warn.log
        fi
        mm_splash_command "log ${MESSAGE}"
    fi
}

mm_uniq() {

    local ARG

    if [ $# -eq 0 ] ; then
        ARG=
        local line=
        while read line ; do
            ARG="${ARG} ${line}"
        done
    else
        ARG=$1
    fi

    /bin/echo `/bin/echo "${ARG}" | /bin/sed -e 's% %\n%g' | /usr/bin/sort | /usr/bin/uniq | /bin/sed -e :a -e '$!N;s/\n/ /;ta' -e 'P;D'`
}

#-------------------------------------------------------------------------------
# mm_url_mount
#
# This function mounts a remote directory as a local directory.
#
# This function takes three arguments:
#     URL: required argument:
#         A URL that points to the remote directory. A URL must have the
#         following form:
#             <protocol>://<username>:<password>@<server>/<path>?<options>
#         where <options> are additional mount options (-o).
#         For example:
#             nfs://server.home/home/public/music
#             cifs://user:pass@server.home/home/public/music,domain=home
#             confrw:themecaches/G.A.N.T..1024.768.sfs<br/>
#         The valid protocol values are: 'nfs', 'cifs', 'http', 'tftp',
#         'confro', 'confrw', 'dist', 'hunt' and 'file'. For 'nfs' 'cifs' and
#         'partlbl'.
#         The URL points to a remote directory. For 'http', 'tftp', 'confro',
#         'confrw', 'dist' and 'hunt', the URL points to a remote file. For
#         'file', the URL point to a local directory or file. For 'partlbl' URL
#         point to partition label. A directory or partition will
#         be mounted at the mount point. A file, which can be a squashfs image
#         (*.sfs.), cramfs image (*.cmg) or a tarball file (*.tar.bz2) will be
#         downloaded and mounted at (for *.sfs and *.cmg files) or downloaded
#         and expanded into (for *.tar.bz2 files) the mount point. The 'confro',
#         'confrw', 'dist' and 'hunt' are special MiniMyth specific URLs. A
#         'dist' URL causes MiniMyth to look for the file in the MiniMyth
#         distribution directory (the directory with the MiniMyth root file
#         system squashfs image). A 'confro' URL causes MiniMyth to look for the
#         file in the MiniMyth read-only configuration directory. A 'confrw' URL
#         causes MiniMyth to look for the file in the MiniMyth read-write
#         configuration directory. A 'hunt' URL causes MiniMyth to look for the
#         file first in the MiniMyth distribution directory and second in the
#         MiniMyth read-only configuration directory.
#     MOUNT_DIR: required argument:
#         The local directory (e.g. /mnt/music) where the URL will be mounted.
#-------------------------------------------------------------------------------
mm_url_mount() {
    local URL="$1"
    local MOUNT_DIR="$2"

    local DIR
    local EXTRA_OPTIONS
    local FILE
    local MOUNT_DEVICE
    local MOUNT_OPTIONS
    local MOUNT_VFSTYPE
    local OPTIONS
    local URL_EXT1
    local URL_EXT2
    local URL_EXTMAX
    local URL_FILE
    local URL_OPTIONS
    local URL_PASSWORD
    local URL_PATH
    local URL_PROTOCOL
    local URL_SERVER
    local URL_USERNAME

    /bin/mkdir -p "${MOUNT_DIR}" || return

    URL_PROTOCOL=`/bin/echo "${URL}" | /usr/bin/cut -d? -f1 | \
                        /usr/bin/cut -d: -f1`
    URL_USERNAME=`/bin/echo "${URL}" | /usr/bin/cut -d? -f1 | \
                        /bin/sed 's%^[^:]*:%%' | /bin/sed 's%^//%%' | /bin/sed 's%[^@]*$%%'  | /bin/sed 's%@$%%' | /usr/bin/cut -d: -f1`
    URL_PASSWORD=`/bin/echo "${URL}" | /usr/bin/cut -d? -f1 | \
                        /bin/sed 's%^[^:]*:%%' | /bin/sed 's%^//%%' | /bin/sed 's%[^@]*$%%'  | /bin/sed 's%@$%%' | /usr/bin/cut -d: -f2`
    URL_SERVER=`  /bin/echo "${URL}" | /usr/bin/cut -d? -f1 | \
                        /bin/sed 's%^[^:]*:%%' | /bin/sed 's%^//%%' | /bin/sed 's%^[^@]*@%%' | /bin/sed 's%/[^/]*%%g'`
    URL_PATH=`    /bin/echo "${URL}" | /usr/bin/cut -d? -f1 | \
                        /bin/sed 's%^[^:]*:%%' | /bin/sed 's%^//[^/]*/%/%'`
    URL_OPTIONS=` /bin/echo "${URL}"                        | \
                        /bin/sed 's%^[^?]*%%'  | /bin/sed 's%^?%%'`

    URL_FILE=`    /bin/echo "${URL_PATH}" | /bin/sed 's%^.*/%%'`
    URL_EXTMAX=`  /bin/echo "${URL_FILE}" | /bin/sed 's%^.*/%%' |/bin/sed 's%[^.]*%%g' | /usr/bin/wc -c` 
    URL_EXT1=
    /usr/bin/test ${URL_EXTMAX} -ge 1 && URL_EXT1=`/bin/echo ${URL_FILE} | /bin/sed 's%^.*/%%' | /usr/bin/cut -s -d. -f$((${URL_EXTMAX}-0))`
    URL_EXT2=
    /usr/bin/test ${URL_EXTMAX} -ge 2 && URL_EXT2=`/bin/echo ${URL_FILE} | /bin/sed 's%^.*/%%' | /usr/bin/cut -s -d. -f$((${URL_EXTMAX}-1))`

    MOUNT_VFSTYPE=""
    EXTRA_OPTIONS=""
    MOUNT_DEVICE=""
    MOUNT_OPTIONS="${URL_OPTIONS}"
    if   [ "x${URL_PROTOCOL}" = "xnfs" ] ; then
        MOUNT_VFSTYPE="nfs"
        MOUNT_DEVICE="${URL_SERVER}:${URL_PATH}"
        MOUNT_OPTIONS="nolock,${MOUNT_OPTIONS}"
    elif [ "x${URL_PROTOCOL}" = "xcifs" ] ; then
        MOUNT_VFSTYPE="cifs"
        MOUNT_DEVICE="//${URL_SERVER}${URL_PATH}"
        if [ ! "x${URL_PASSWORD}" = "x" ] ; then
            MOUNT_OPTIONS="password=${URL_PASSWORD},${MOUNT_OPTIONS}"
        fi
        if [ ! "x${URL_USERNAME}" = "x" ] ; then
            MOUNT_OPTIONS="username=${URL_USERNAME},${MOUNT_OPTIONS}"
        fi
    elif ( [ "x${URL_PROTOCOL}" = "xhttp"   ] ) || \
         ( [ "x${URL_PROTOCOL}" = "xtftp"   ] ) || \
         ( [ "x${URL_PROTOCOL}" = "xconfro" ] ) || \
         ( [ "x${URL_PROTOCOL}" = "xconfrw" ] ) || \
         ( [ "x${URL_PROTOCOL}" = "xdist"   ] ) || \
         ( [ "x${URL_PROTOCOL}" = "xhunt"   ] ) || \
         ( [ "x${URL_PROTOCOL}" = "xfile"   ] && [ -f "${URL_PATH}" ] ) ; then
        if  [ "x${URL_EXT1}" = "xsfs" ] ; then
            DIR="/initrd/rw/loopfs/`/bin/echo ${MOUNT_DIR} | /bin/sed 's%//*%~%g'`"
            FILE="image.sfs"
            /bin/mkdir -p "${DIR}"
            /bin/mkdir -p "${DIR}/ro"
            /bin/mkdir -p "${DIR}/rw"
            /bin/mkdir -p "${DIR}/wrk"
            cd "${DIR}"
            mm_url_${URL_PROTOCOL}_get "${FILE}" "${URL_PATH}" "${URL_SERVER}"          || return
            /bin/mount -t squashfs -o loop "${DIR}/${FILE}" "${DIR}/ro"                 || return
            /bin/mount -t overlay -o lowerdir="${DIR}/ro",upperdir="${DIR}/rw",workdir="${DIR}/wrk" none "${MOUNT_DIR}" || return
        elif [ "x${URL_EXT1}" = "xcmg" ] ; then
            DIR="/initrd/rw/loopfs/`/bin/echo ${MOUNT_DIR} | /bin/sed 's%//*%~%g'`"
            FILE="image.cmg"
            /bin/mkdir -p "${DIR}"
            /bin/mkdir -p "${DIR}/ro"
            /bin/mkdir -p "${DIR}/rw"
            /bin/mkdir -p "${DIR}/wrk"
            cd "${DIR}"
            mm_url_${URL_PROTOCOL}_get "${FILE}" "${URL_PATH}" "${URL_SERVER}"          || return
            /bin/mount -t cramfs -o loop "${DIR}/${FILE}" "${DIR}/ro"                   || return
            /bin/mount -t overlay -o lowerdir="${DIR}/ro",upperdir="${DIR}/rw",workdir="${DIR}/wrk" none "${MOUNT_DIR}" || return
        elif [ "x${URL_EXT1}" = "xbz2" ] && [ "x${URL_EXT2}" = "xtar" ] ; then
            FILE="tmp.tar.bz2~"
            cd "${MOUNT_DIR}"
            mm_url_${URL_PROTOCOL}_get "${FILE}" "${URL_PATH}" "${URL_SERVER}" || return
            /bin/tar -jxf "${FILE}"                                            || return
            /bin/rm -f "${FILE}"                                               || return
        fi
    elif [ "x${URL_PROTOCOL}" = "xfile" ] && [ -d "${URL_PATH}" ] ; then
        /bin/mount --rbind "${URL_PATH}" "${MOUNT_DIR}"
    elif [ "x${URL_PROTOCOL}" = "xpartlbl" ] ; then
        LABEL=`/bin/echo ${URL_PATH} | /bin/sed 's%/*%%g'`
        /bin/mount --label "${LABEL}" "${MOUNT_DIR}"
    else
        /usr/bin/logger -s -t minimyth -p "local0.error" \
            "mm_url_mount: protocol '${URL_PROTOCOL}' is not supported."
        /bin/false
        return
    fi

    if [ -n "${MOUNT_VFSTYPE}" ] ; then
        OPTIONS=""
        MOUNT_OPTIONS=`/bin/echo ${MOUNT_OPTIONS} | /bin/sed 's%^,%%'`
        MOUNT_OPTIONS=`/bin/echo ${MOUNT_OPTIONS} | /bin/sed 's%,$%%'`
        MOUNT_OPTIONS=`/bin/echo ${MOUNT_OPTIONS} | /bin/sed 's%^  *%%'`
        MOUNT_OPTIONS=`/bin/echo ${MOUNT_OPTIONS} | /bin/sed 's%  *$%%'`
        /usr/bin/test -n "${EXTRA_OPTIONS}" && OPTIONS="${EXTRA_OPTIONS}"
        /usr/bin/test -n "${MOUNT_OPTIONS}" && OPTIONS="${OPTIONS} -o ${MOUNT_OPTIONS}"
        OPTIONS=`/bin/echo ${OPTIONS} | /bin/sed 's%^  *%%'`
        OPTIONS=`/bin/echo ${OPTIONS} | /bin/sed 's%  *$%%'`
        /bin/mount -n -t "${MOUNT_VFSTYPE}" ${OPTIONS} "${MOUNT_DEVICE}" "${MOUNT_DIR}" || return
    fi

    return
}

mm_url_umount() {
    local URL="$1"
    local MOUNT_DIR="$2"

    local DIR
    local FILE
    local URL_EXT1
    local URL_EXT2
    local URL_EXTMAX
    local URL_FILE
    local URL_PATH
    local URL_PROTOCOL

    URL_PROTOCOL=`/bin/echo "${URL}" | /usr/bin/cut -d? -f1 | \
                        /usr/bin/cut -d: -f1`
    URL_PATH=`    /bin/echo "${URL}" | /usr/bin/cut -d? -f1 | \
                        /bin/sed 's%^[^:]*:%%' | /bin/sed 's%^//[^/]*/%/%'`

    URL_FILE=`    /bin/echo "${URL_PATH}" | /bin/sed 's%^.*/%%'`
    URL_EXTMAX=`  /bin/echo "${URL_FILE}" | /bin/sed 's%^.*/%%' |/bin/sed 's%[^.]*%%g' | /usr/bin/wc -c` 
    URL_EXT1=
    /usr/bin/test ${URL_EXTMAX} -ge 1 && URL_EXT1=`/bin/echo ${URL_FILE} | /bin/sed 's%^.*/%%' | /usr/bin/cut -s -d. -f$((${URL_EXTMAX}-0))`
    URL_EXT2=
    /usr/bin/test ${URL_EXTMAX} -ge 2 && URL_EXT2=`/bin/echo ${URL_FILE} | /bin/sed 's%^.*/%%' | /usr/bin/cut -s -d. -f$((${URL_EXTMAX}-1))`

    if [ "x${URL_PROTOCOL}" = "xnfs"     ] || \
       [ "x${URL_PROTOCOL}" = "xpartlbl" ] || \
       [ "x${URL_PROTOCOL}" = "xcifs"    ] ; then
        if [ -d "${MOUNT_DIR}" ] ; then
            /bin/umount -f "${MOUNT_DIR}"
        fi
    elif ( [ "x${URL_PROTOCOL}" = "xhttp"   ] ) || \
         ( [ "x${URL_PROTOCOL}" = "xtftp"   ] ) || \
         ( [ "x${URL_PROTOCOL}" = "xconfro" ] ) || \
         ( [ "x${URL_PROTOCOL}" = "xconfrw" ] ) || \
         ( [ "x${URL_PROTOCOL}" = "xdist"   ] ) || \
         ( [ "x${URL_PROTOCOL}" = "xhunt"   ] ) || \
         ( [ "x${URL_PROTOCOL}" = "xfile"   ] && [ -f "${URL_PATH}" ] ) ; then
        if [ "x${URL_EXT1}" = "xsfs" ] ; then
            DIR="/initrd/rw/loopfs/`/bin/echo ${MOUNT_DIR} | /bin/sed 's%//*%~%g'`"
            FILE="image.sfs"
            if [ -d "${MOUNT_DIR}" ] ; then
                /bin/umount -f "${MOUNT_DIR}"
            fi
            if [ -d "${DIR}/ro" ] ; then
                /bin/umount -f "${DIR}/ro"
            fi
            rm -f "${DIR}/${FILE}"
        elif [ "x${URL_EXT1}" = "xcmg" ] ; then
            DIR="/initrd/rw/loopfs/`/bin/echo ${MOUNT_DIR} | /bin/sed 's%//*%~%g'`"
            FILE="image.cmg"
            if [ -d "${MOUNT_DIR}" ] ; then
                /bin/umount -f "${MOUNT_DIR}"
            fi
            if [ -d "${DIR}/ro" ] ; then
                /bin/umount -f "${DIR}/ro"
            fi
            rm -f "${DIR}/${FILE}"
        elif [ "x${URL_EXT1}" = "xbz2" ] && [ "x${URL_EXT2}" = "xtar" ] ; then
            /bin/rm -rf "${MOUNT_DIR}"
        fi
    else
        /usr/bin/logger -s -t minimyth -p "local0.error" \
            "mm_url_umount: protocol '${URL_PROTOCOL}' is not supported."
        /bin/false
        return
    fi

    /bin/true
    return
}

mm_var_get() {
    local VAR=$1

    /bin/echo `set | /bin/grep "^${VAR}=" | /bin/sed 's%^[^=]*=%%' | /bin/sed "s%^'%%" | /bin/sed "s%'$%%"`
}

#===============================================================================
# splash screen functions
#===============================================================================
_mm_var_splash_command='/usr/sbin/fbsplashd'
_mm_var_splash_command_path=`/bin/echo ${_mm_var_splash_command} | /usr/bin/cut -d ' ' -f 1`
_mm_var_splash_command_dir=`/usr/bin/dirname ${_mm_var_splash_command_path}`
_mm_var_splash_command_base=`/usr/bin/basename ${_mm_var_splash_command_path}`
_mm_var_splash_fifo='/lib/splash/cache/.splash'
_mm_var_splash_fifo_dir=`/usr/bin/dirname ${_mm_var_splash_fifo}`
_mm_var_splash_fifo_base=`/usr/bin/basename ${_mm_var_splash_fifo}`
_mm_var_splash_progress_val=1
_mm_var_splash_progress_max=1

mm_splash_running_test() {
    if [ -n "`/bin/pidof ${_mm_var_splash_command_base}`" ] && [ -e ${_mm_var_splash_fifo} ] ; then
        return 0
    else
        return 1
    fi
}

mm_splash_init() {
    local type=$1

    local message

    local DEPTH
    local GEOMETRY
    local LOGLEVEL
    local SPLASH_ENABLE
    local VXRES
    local VYRES
    local XRES
    local YRES
    local XHWTYPE

    SPLASH_ENABLE=yes

    # Disable splash screen when more than kernel critical messages are logged to the console.
    # That is when the loglevel is greater than 3.
    if [ "x${SPLASH_ENABLE}" = "xyes" ] ; then
        LOGLEVEL=`/bin/cat /proc/sys/kernel/printk | /usr/bin/cut -f 1`
        if [ -z "${LOGLEVEL}" ] ; then
            SPLASH_ENABLE='no'
            /usr/bin/logger -t minimyth -p "local0.info" "disabling splash screen due no loglevel is set"
        fi
        if [ -n "${LOGLEVEL}" ] && [ ${LOGLEVEL} -gt 3 ] ; then
            SPLASH_ENABLE='no'
            /usr/bin/logger -t minimyth -p "local0.info" "disabling splash screen due loglevel > 3"
        fi
    fi

    # Disable splash screen when there is no framebuffer device.
    if [ "x${SPLASH_ENABLE}" = "xyes" ] ; then
        if [ ! -e '/dev/fb0' ] ; then 
            SPLASH_ENABLE='no'
            /usr/bin/logger -t minimyth -p "local0.info" "disabling splash screen due no /dev/fb0 framebuffer found"
        fi
    fi

    # Disable splash screen when the video resolution is not compatible.
    # That is when the resolution is not 640x480 or color depth is less than 16.
    if [ "x${SPLASH_ENABLE}" = "xyes" ] ; then
        GEOMETRY=`/usr/sbin/fbset | /bin/grep geometry`
        XRES=` /bin/echo ${GEOMETRY} | /usr/bin/cut -d ' ' -f 2`
        YRES=` /bin/echo ${GEOMETRY} | /usr/bin/cut -d ' ' -f 3`
        VXRES=`/bin/echo ${GEOMETRY} | /usr/bin/cut -d ' ' -f 4`
        VYRES=`/bin/echo ${GEOMETRY} | /usr/bin/cut -d ' ' -f 5`
        DEPTH=`/bin/echo ${GEOMETRY} | /usr/bin/cut -d ' ' -f 6`
        if [ -z "${XRES}"  ] || \
           [ -z "${YRES}"  ] || \
           [ -z "${VXRES}" ] || \
           [ -z "${VYRES}" ] || \
           [ -z "${DEPTH}" ] ; then
            SPLASH_ENABLE='no'
            /usr/bin/logger -t minimyth -p "local0.info" "disabling splash due unknown gemoetry (Xres:${XRES},Yres:${YRES},VXres:${VXRES},VYres:${VYRES},Depth:${DEPTH}"
        fi
    fi

    if [ "x${SPLASH_ENABLE}" = "xyes" ] ; then
        case "${type}" in
            bootup)   message="starting system ..."      ;;
            shutdown) message="shutting down system ..." ;;
            reboot)   message="restarting system ..."    ;;
            *)        message="${type}"                  ;;
        esac
        /usr/bin/logger -t minimyth -p "local0.info" "starting splash screen. geometry:${XRES}x${YRES},Vres:${VXRES}x${VYRES},${DEPTH}bpp"
        /usr/bin/chvt 1
        /bin/mkdir -p "${_mm_var_splash_fifo_dir}"
        mm_splash_command "exit"
        ${_mm_var_splash_command} --theme="minimyth" --progress="0" --mesg="${message}" --type="${type}"
        mm_splash_command "set mode silent"
        mm_splash_command "repaint"
    fi

    mm_splash_progress_set 0 1

    return 0
}

mm_splash_halt() {

    /usr/bin/logger -t minimyth -p "local0.info" "stopping splash screen"

    mm_splash_command "exit"

    return 0
}

mm_splash_command()
{
    /usr/bin/test `mm_splash_running_test ; /bin/echo $?` -eq 0 && /bin/echo "$1" >> "${_mm_var_splash_fifo}"

    return 0
}

mm_splash_message_output() {
    local MESSAGE=$1

    mm_splash_command "set message ${MESSAGE}"
    mm_splash_command "repaint"

    return 0
}

mm_splash_progress_set() {
    _mm_var_splash_progress_val=$1
    _mm_var_splash_progress_max=$2
 
    /usr/bin/test ${_mm_var_splash_progress_val} -gt ${_mm_var_splash_progress_max} && _mm_var_splash_progress_val=${_mm_var_splash_progress_max}
    mm_splash_command "progress $(( 65535 * ${_mm_var_splash_progress_val} / ${_mm_var_splash_progress_max} ))"
    mm_splash_command "repaint"

    return 0
}

mm_splash_progress_update() {
    _mm_var_splash_progress_val=$((_mm_var_splash_progress_val + 1))
    /usr/bin/test ${_mm_var_splash_progress_val} -gt ${_mm_var_splash_progress_max} && _mm_var_splash_progress_val=${_mm_var_splash_progress_max}
    mm_splash_command "progress $(( 65535 * ${_mm_var_splash_progress_val} / ${_mm_var_splash_progress_max} ))"
    mm_splash_command "repaint"

    return 0
}

#===============================================================================
# mythdb functions.
#===============================================================================
mm_mythdb_buffer_write() {
    local FLUSH=$1
    local COMMAND=$2

    local RETURN

    RETURN=0

    # If buffering is not enabled, then enable flush.
    if [ ! -e /var/cache/mythdb/buffer.enable ] ; then
        FLUSH=1
    fi

    # If mythdb cache directory does not exist, then create it.
    if [ ! -e /var/cache/mythdb/ ] ; then
        /bin/mkdir -p /var/cache/mythdb/
    fi

    # If there is a command, then write it to the buffer.
    if [ -n "${COMMAND}" ] ; then
        /bin/echo "${COMMAND}" >> /var/cache/mythdb/buffer.sql
    fi

    # If flush enabled and there is a buffer, then flush the buffer.
    if [ ${FLUSH} -ne 0 ] ; then
        if [ -e /var/cache/mythdb/buffer.sql ] ; then
            /usr/bin/mysql \
                --host=${MM_MASTER_SERVER} \
                --user=${MM_MASTER_DBUSERNAME} \
                --password=${MM_MASTER_DBPASSWORD} \
                --database=${MM_MASTER_DBNAME} \
                < /var/cache/mythdb/buffer.sql
            RETURN=$?
            /bin/rm -f /var/cache/mythdb/buffer.sql
        fi
    fi

    return ${RETURN}
}

mm_mythdb_buffer_create() {
    /bin/mkdir -p /var/cache/mythdb/
    /bin/touch /var/cache/mythdb/buffer.enable

    return 0
}

mm_mythdb_buffer_delete() {

    local RETURN

    mm_mythdb_buffer_write 1
    RETURN=$?
    /bin/rm -f /var/cache/mythdb/buffer.enable

    return ${RETURN}
}

mm_mythdb_test() {

    local RETURN

    mm_mythdb_buffer_write 1 ";"
    RETURN=$?

    return ${RETURN}
}

mm_mythdb_get() {
    local COMMAND=$1

    local RETURN

    mm_mythdb_buffer_write 1 "${COMMAND} ;"
    RETURN=$?

    return ${RETURN}
}

mm_mythdb_set() {
    local COMMAND=$1

    local RETURN

    mm_mythdb_buffer_write 0 "${COMMAND} ;"
    RETURN=$?

    return ${RETURN}
}

mm_mythdb_jumppoints_delete() {
    local DESTINATION=$1

    local HOST_NAME

    HOST_NAME=`/bin/hostname`

    if [ -n "${DESTINATION}" ] ; then
        mm_mythdb_set "DELETE FROM jumppoints \
            WHERE hostname=\"${HOST_NAME}\" AND destination=\"${DESTINATION}\""
    else
        mm_mythdb_set "DELETE FROM jumppoints \
            WHERE hostname=\"${HOST_NAME}\""
    fi
}

mm_mythdb_jumppoints_dump() {
    local DESTINATION=$1

    local HOST_NAME

    HOST_NAME=`/bin/hostname`

    if [ -n "${DESTINATION}" ] ; then
        mm_mythdb_get "SELECT * FROM jumppoints \
            WHERE hostname=\"${HOST_NAME}\" AND destination=\"${DESTINATION}\""
    else
        mm_mythdb_get "SELECT * FROM jumppoints \
            WHERE hostname=\"${HOST_NAME}\""
    fi
}

mm_mythdb_jumppoints_update() {
    local DESTINATION=$1
    local KEYLIST=$2

    local HOST_NAME

    HOST_NAME=`/bin/hostname`

    mm_mythdb_set "UPDATE jumppoints SET keylist=\"${KEYLIST}\" \
        WHERE hostname=\"${HOST_NAME}\" AND destination=\"${DESTINATION}\""
}

mm_mythdb_jumppoints_get() {
    local VALUE=$1

    local DATA

    DATA=`mm_mythdb_jumppoints_dump "$1" | /bin/grep -e "$1" |  /usr/bin/cut -f 3`

    /bin/echo "${DATA}"
}

mm_mythdb_keybindings_delete() {
    local CONTEXT=$1
    local ACTION=$2

    local HOST_NAME

    HOST_NAME=`/bin/hostname`

    if   [ -n "${CONTEXT}" ] && [ -n "${ACTION}" ] ; then
        mm_mythdb_set "DELETE FROM keybindings \
            WHERE hostname=\"${HOST_NAME}\" AND context=\"${CONTEXT}\" AND action=\"${ACTION}\""
    elif [ -n "${CONTEXT}" ] ; then
        mm_mythdb_set "DELETE FROM keybindings \
            WHERE hostname=\"${HOST_NAME}\" AND context=\"${CONTEXT}\""
    else
        mm_mythdb_set "DELETE FROM keybindings \
            WHERE hostname=\"${HOST_NAME}\""
    fi
}

mm_mythdb_keybindings_dump() {
    local CONTEXT=$1
    local ACTION=$2

    local HOST_NAME

    HOST_NAME=`/bin/hostname`

    if   [ -n "${CONTEXT}" ] && [ -n "${ACTION}" ] ; then
        mm_mythdb_get "SELECT * FROM keybindings \
            WHERE hostname=\"${HOST_NAME}\" AND context=\"${CONTEXT}\" AND action=\"${ACTION}\""
    elif [ -n "${CONTEXT}" ] ; then
        mm_mythdb_get "SELECT * FROM keybindings \
            WHERE hostname=\"${HOST_NAME}\" AND context=\"${CONTEXT}\""
    else
        mm_mythdb_get "SELECT * FROM keybindings \
            WHERE hostname=\"${HOST_NAME}\""
    fi
}

mm_mythdb_keybindings_update() {
    local CONTEXT=$1
    local ACTION=$2
    local KEYLIST=$3

    local HOST_NAME

    HOST_NAME=`/bin/hostname`

    mm_mythdb_set "UPDATE keybindings SET keylist=\"${KEYLIST}\" \
        WHERE hostname=\"${HOST_NAME}\" AND context=\"${CONTEXT}\" AND action=\"${ACTION}\""
}

mm_mythdb_music_playlists_dump() {
    mm_mythdb_set "SELECT * FROM music_playlists"
}

mm_mythdb_music_playlists_scope() {
    local MUSICPLAYLIST=$1
    local SCOPE=$2

    local HOST_NAME

    HOST_NAME=`/bin/hostname`

    case "${SCOPE}" in
        local)
            mm_mythdb_set "UPDATE music_playlists SET hostname=\"${HOST_NAME}\" WHERE playlist_name=\"${MUSICPLAYLIST}\""
            ;;
        global)
            mm_mythdb_set "UPDATE music_playlists SET hostname=\"\"             WHERE playlist_name=\"${MUSICPLAYLIST}\""
            ;;
    esac
}

mm_mythdb_settings_delete() {
    local VALUE=$1

    local HOST_NAME

    HOST_NAME=`/bin/hostname`

    if [ -n "${VALUE}" ] ; then
        mm_mythdb_set "DELETE FROM settings WHERE value=\"${VALUE}\" AND hostname=\"${HOST_NAME}\""
    else
        mm_mythdb_set "DELETE FROM settings WHERE hostname=\"${HOST_NAME}\""
    fi
}

mm_mythdb_settings_dump() {
    local VALUE=$1

    local HOST_NAME

    HOST_NAME=`/bin/hostname`

    if [ -n "${VALUE}" ] ; then
        mm_mythdb_get "SELECT * FROM settings WHERE value=\"${VALUE}\" AND hostname=\"${HOST_NAME}\""
    else
        mm_mythdb_get "SELECT * FROM settings WHERE hostname=\"${HOST_NAME}\""
    fi
}

mm_mythdb_settings_update() {
    local VALUE=$1
    local DATA=$2

    local HOST_NAME

    HOST_NAME=`/bin/hostname`

    mm_mythdb_set "UPDATE settings SET data=\"${DATA}\" WHERE value=\"${VALUE}\" AND hostname=\"${HOST_NAME}\""
}

mm_mythdb_settings_set() {
    local VALUE=$1
    local DATA=$2

    local HOST_NAME
    local DATA_CURRENT

    HOST_NAME=`/bin/hostname`

    mm_mythdb_settings_delete "${VALUE}"
    mm_mythdb_set "INSERT INTO settings SET data=\"${DATA}\", value=\"${VALUE}\", hostname=\"${HOST_NAME}\""
}

mm_mythdb_settings_get() {
    local VALUE=$1

    local DATA

    DATA=`mm_mythdb_settings_dump "$1" | /bin/grep -e "$1" |  /usr/bin/cut -f 2`

    /bin/echo "${DATA}"
}


#===============================================================================
# Hardware processing functions.
#===============================================================================

#-------------------------------------------------------------------------------
#-------------------------------------------------------------------------------
mm_hardware_cpu_process() {
    local cpu_process_function=$1

    local vendor
    local family
    local model

    # We only check the first CPU.
    # Thus, wea are assuming all other CPU are the same as the first.
    vendor=`/bin/grep '^vendor_id[[:cntrl:]]*:'  /proc/cpuinfo | /usr/bin/head -n1 | /usr/bin/awk -F ": " '{ print $2 }'`
    family=`/bin/grep '^cpu family[[:cntrl:]]*:' /proc/cpuinfo | /usr/bin/head -n1 | /usr/bin/awk -F ": " '{ print $2 }'`
    model=` /bin/grep '^model[[:cntrl:]]*:'      /proc/cpuinfo | /usr/bin/head -n1 | /usr/bin/awk -F ": " '{ print $2 }'`

    /bin/echo `${cpu_process_function} ${vendor} ${family} ${model}` | mm_uniq
}

mm_hardware_cpu2kernel_map() {
    local vendor=$1
    local family=$2
    local model=$3

    local map
    local map_kernel_modules

    if [ -n "${vendor}" ] ; then
        /bin/cat /etc/hardware.d/cpu2kernel.map                                                                 \
        | /bin/sed -e 's%#.*$%%g' | /bin/sed -e 's% *, *%,%g' | /bin/sed -e 's%^  *%%' | /bin/sed -e 's%  *$%%' \
        | /bin/grep -e "^${vendor},"                                                                            \
        | {
            while read map ; do
                if [ -n "${map}" ] ; then
                    map_family=`        /bin/echo ${map} | /usr/bin/cut -d ',' -f 2`
                    map_model=`         /bin/echo ${map} | /usr/bin/cut -d ',' -f 3`
                    map_kernel_modules=`/bin/echo ${map} | /usr/bin/cut -d ',' -f 4`
                    if ( [ -z "${map_family}" ] || [ "x${map_family}" = "x${family}" ] ) && \
                       ( [ -z "${map_model}"  ] || [ "x${map_model}"  = "x${model}"  ] ) ; then
                        /bin/echo ${map_kernel_modules}
                    fi
                fi
            done
        }
    fi
}

mm_hardware_x2kernel_map() {
    local x_driver=$1

    local found
    local map
    local map_kernel_module

    if [ -n "${x_driver}" ] ; then
        /bin/cat /etc/hardware.d/x2kernel.map                                                                   \
        | /bin/sed -e 's%#.*$%%g' | /bin/sed -e 's% *, *%,%g' | /bin/sed -e 's%^  *%%' | /bin/sed -e 's%  *$%%' \
        | /bin/grep -e "^${x_driver},"                                                                          \
        | {
            found=
            while read map ; do
                map_kernel_module=
                if [ -n "${map}" ] ; then
                    map_kernel_module=`/bin/echo ${map} | /usr/bin/cut -d ',' -f 2`
                fi
                if [ -z "${found}" ] ; then
                    found=1
                    /bin/echo ${map_kernel_module}
                fi
            done
        }
    fi
}

#===============================================================================
# X functions.
#===============================================================================
mm_x_xmacroplay() {
    program="$1"
    command="$2"

    # Make sure that the program is running.
#    if [ -n "`/bin/pidof ${program}`" ] ; then
        # Make sure that the X window manager is running, since we depend on it to select the program window.
        if [ -n "`/bin/pidof ratpoison`" ] ; then
            # Set ratpoison to select window by program name.
            /usr/bin/ratpoison -d :0.0 -c "set winname class"
            # Select the program window.
            /usr/bin/ratpoison -d :0.0 -c "select ${program}"
            # Make sure the program window is selected. 
            window=`/usr/bin/ratpoison -d :0.0 -c "info" 2> /dev/null`
            /usr/bin/logger -t minimyth -p "local0.info" "[functions] xmacroplay ratpoison info returns:${window}"
            window=`/usr/bin/ratpoison -d :0.0 -c "info" 2> /dev/null | /bin/sed -e 's%^.*(\([^()]*\))$%\1%'`
            /usr/bin/logger -t minimyth -p "local0.info" "[functions] xmacroplay after grep:${window}"
            /bin/echo "${window}" | /bin/grep -q -i "${program}" 2> /dev/null
            if [ $? -eq 0 ] ; then
                # Send exit key sequence to window.
                /usr/bin/logger -t minimyth -p "local0.info" "[functions] xmacroplay sending command:${command}"
                /bin/echo -e "${command}" | /usr/bin/xmacroplay -d 100 :0.0 > /dev/null 2>&1
            fi
        else
            mm_message_output error "cannot command '${program}' without X window manager enabled."
        fi
#    fi
}

# Expand the applications list.
#
# The applications list contains names of applications or names of application
# groups. Application groups are identified by preceeding them with a ':'. The
# following groups:
#   :everything
#   :myth
#   :game
#   :terminal
mm_x_applications_list() {
    local applications="$@"

    # Remove line breaks and convert all control characters to spaces.
    applications=`/bin/echo  "${applications}"  | /bin/sed -e :a -e '$!N;s/\n/ /;ta' -e 'P;D'`
    applications=`/bin/echo  "${applications}"  | /bin/sed -e 's%[[:cntrl:]]% %g'`

    # Convert application groups to application names.
    applications=`/bin/echo " ${applications} " | /bin/sed -e 's% :everything % :game :terminal :myth %g'`
    applications=`/bin/echo " ${applications} " | /bin/sed -e 's% :myth % mythfrontend %g'`    
    applications=`/bin/echo " ${applications} " | /bin/sed -e 's% :game % fceu jzintv mame mess mednafen stella VisualBoyAdvance zsnes %g'`
    applications=`/bin/echo " ${applications} " | /bin/sed -e 's% :terminal % rxvt %g'`

    # Clean up spaces.
    applications=`/bin/echo  "${applications}"  | /bin/sed -e 's%  *% %g' -e 's%^ %%' -e 's% $%%'`

    /bin/echo "${applications}"
}

# Exit all applications in the list, assuming that we know how.
mm_x_applications_exit() {
    local applications=`mm_x_applications_list "$@"`

    local application
    local timeout
    local window
    local xmacro

    for application in ${applications} ; do
        if [ -n "`/bin/pidof ${application}`" ] ; then
            window=""
            xmacro=""
            case "${application}" in
                mythfrontend)     xmacro='KeyStr Escape\n KeyStr Escape\n KeyStrPress Control_L\n KeyStr Escape\n KeyStrRelease Control_L\n' ;;
                fceu)             xmacro='KeyStr Escape\n'                                                                     ;;
                jzintv)           xmacro='KeyStr F1\n'                                                                         ;;
                mame)             xmacro='KeyStr Escape\n'                                                                     ;;
                mess)             xmacro='KeyStr Escape\n'                                                                     ;;
                mednafen)         xmacro='KeyStr Escape\n'                                                                     ;;
                stella)           xmacro='KeyStrPress Control_L\n KeyStrPress Q\n KeyStrRelease Q\n KeyStrRelease Control_L\n' ;;
                VisualBoyAdvance) xmacro='KeyStr Escape\n'                                                                     ;;
                zsnes)            xmacro='KeyStr Escape\n KeyStr Q\n KeyStr Return\n'                                          ;;
                # Terminals
                # Does not work because rxvt does not have a key sequence to quit.  Also, the window is named 'xterm' not 'rxvt'.
                # rxvt)             xmacro=''                                                                                    ;;
            esac
            if [ -n "${xmacro}" ] ; then
                mm_x_xmacroplay "${application}" "${xmacro}"
                if [ -n "`/bin/pidof ${application}`" ] ; then
                    /usr/bin/logger -t minimyth -p "local0.info" "[functions/mm_x_start] '${application}' failed to exit..."
                fi
            fi
        fi
    done
}

# Kill all applications in the list.
mm_x_applications_kill() {
    local applications=`mm_x_applications_list "$@"`

    local application

    for application in ${applications} ; do
        pids="`/bin/pidof ${application}`"
        for pid in ${pids} ; do
            /bin/kill -SIGTERM ${pid} > /dev/null 2>&1
        done
    done

    return 0
}

# Wait until all applications in the list are dead.
mm_x_applications_dead() {
    local applications=`mm_x_applications_list "$@"`

    local application

    for application in ${applications} ; do
        if [ -n "`/bin/pidof ${application}`" ] ; then
            /usr/bin/logger -t minimyth -p "local0.info" "[functions/mm_x_applications_dead] Apps. not dying:[${application}]"
            /bin/sleep 1
            /usr/bin/logger -t minimyth -p "local0.info" "[functions/mm_x_applications_dead] Killing [${application}]"
            pids="`/bin/pidof ${application}`"
            for pid in ${pids} ; do
                /bin/kill -SIGKILL ${pid} > /dev/null 2>&1
            done
        fi
    done

    return 0
}

# Start X.
mm_x_start() {

    local mailnotifypid
    local timeout=60

    /usr/bin/logger -t minimyth -p "local0.info" "[functions/mm_x_start] Starting procedure for start X..."

    # Only root start X.
    if [ ! `/usr/bin/id -u` -eq 0 ] ; then
        /usr/bin/logger -t minimyth -p "local0.info" "[functions/mm_x_start] X not started because uid=`/usr/bin/id -u` returns not 'root'"
        return 0
    fi

    # Only start X if X is enabled.
    if [ ! "x${MM_X_ENABLED}" = "xyes" ] ; then
        /usr/bin/logger -t minimyth -p "local0.info" "[functions/mm_x_start] starting TTY terminal because X not enabled in minimyth.conf"
        if /usr/bin/test -z "`/bin/pidof agetty`" ; then
            /sbin/agetty 9600 tty1 &
        fi
        return 0
    fi

    # Only start X if X is not already running.
    if [ -n "`/bin/pidof X`" ] ; then
        /usr/bin/logger -t minimyth -p "local0.info" "[functions/mm_x_start] X not started because X is already running"
        return 0
    fi

    # Awaiting till all sequential init scripts will be executed
    /usr/bin/logger -t minimyth -p "local0.info" "[functions/mm_x_start] Starting wait for sequential init scripts are executed..."
    i=0
    while [ $i -lt ${timeout} ] ; do
        in_progress=`/bin/ls -1 /var/lib/init/*.inprogress 2>/dev/null`
        i=$((${i} + 1))
        if [  "x${in_progress}" = "x" ] ; then
            /usr/bin/logger -t minimyth -p "local0.info" "[functions/mm_x_start] All sequential init scripts done..."
            i=${timeout}
        else
            if [ $i -eq ${timeout} ] ; then
                /usr/bin/logger -t minimyth -p "local0.err" "[functions/mm_x_start] Timeout waiting for finishing following sequential init scripts: \"${in_progress}\""
                /bin/false
                return
            else
                /usr/bin/logger -t minimyth -p "local0.info" "[functions/mm_x_start] Still waiting to finish sequential init scripts. Remains:\"${in_progress}\""
                /bin/sleep 1
            fi
        fi
    done

    if [ "x${MM_MYTHTV_RUN_ON_EGLFS}" = "xyes" ] ; then

        if [ "x${MM_X_MYTH_PROGRAM}" = "xmythfrontend" ] ; then
            /usr/bin/logger -t minimyth -p "local0.info" "[functions/mm_x_start] Kicking mythfrontend on EGLFS..."
            mm_mythfrontend_start
        elif [ "x${MM_X_MYTH_PROGRAM}" = "xmythwelcome" ]  ; then
            /usr/bin/logger -t minimyth -p "local0.info" "[functions/mm_x_start] Kicking mythwelcome on EGLFS..."
            mm_mythwelcome_start
        fi

    else
        /usr/bin/logger -t minimyth -p "local0.info" "[functions/mm_x_start] Kicking Xinit..."

        /usr/bin/prlimit --rtprio=50 /bin/su -c "/usr/bin/nohup /usr/bin/xinit > /dev/null 2>&1 &" - minimyth

        # Start xscreensaver if enabled
        if [ "x${MM_X_SCREENSAVER_HACK}" = "xsleep" ] ; then
            if [ -z `/bin/pidof mm_sleep_on_ss` ] ; then
                /usr/bin/mm_sleep_on_ss &
                /usr/bin/logger -t minimyth -p "local0.info" "[functions/mm_x_start] Starting SLEEP_ON_SS script..."
            fi
        fi
    fi

    # Start myth watchdog if enabled
    if [ "x${MM_X_WATCHDOG_MYTH_PROC}" = "xyes" ] ; then
        /usr/bin/mm_watchdog &
        /usr/bin/logger -t minimyth -p "local0.info" "[functions/mm_x_start] Starting MM_WATCHDOG script..."
    fi

    # Auto-configure usage of 'irxevent'.
    if [ "x${MM_LIRC_IRXEVENT_ENABLED}" = "xauto" ] ; then
        /usr/bin/logger -t minimyth -p "local0.info" "[functions/mm_x_start] Attempting to auto-configure usage of irxevent"
            MM_LIRC_IRXEVENT_ENABLED='no'
            if [ -e /etc/lirc/lircrc ] ; then
                # Only one level of includes is supported.
                lircrc_files="/etc/lirc/lircrc `/bin/cat /etc/lirc/lircrc | /bin/grep -e '^include ' | /bin/sed -e 's%^include *%%'`"
                for lircrc_file in ${lircrc_files} ; do
                    if [ `/bin/cat ${lircrc_file} | /bin/grep -q -e '^ *prog *= *irxevent'` ] ; then
                        MM_LIRC_IRXEVENT_ENABLED='yes'
                    fi
                done
            fi
    fi

    # Start the irxevent daemon.
    if [ "x${MM_LIRC_IRXEVENT_ENABLED}" = "xyes" ] ; then
        /usr/bin/test -n "`/bin/pidof irxevent`" && /usr/bin/killall irxevent
        /bin/sleep 5
        /usr/bin/logger -t minimyth -p "local0.info" "[functions/mm_x_start] Starting irxevent daemon..."
        /usr/bin/irxevent -d /etc/lirc/lircrc
    fi

    return 0
}

# Stop X.
mm_x_stop() {

    local applications

    /usr/bin/logger -t minimyth -p "local0.info" "[functions/mm_x_stop] Starting procedure of stopping X."

    # Only users root and minimyth can stop X.
    if [ ! `/usr/bin/id -u` -eq 0 ] ; then
        /usr/bin/logger -t minimyth -p "local0.info" "[functions/mm_x_stop] X not stopped because uid=`/usr/bin/id -u` returns not 'root'."
        return 0
    fi

    if [ -n "`/bin/pidof irxevent`" ] ; then
        /usr/bin/logger -t minimyth -p "local0.info" "[functions/mm_x_stop] Killing irxevent daemon..."
        /usr/bin/killall irxevent
    fi

    if [ -n "`/bin/pidof mm_sleep_on_ss`" ] ; then
        /usr/bin/logger -t minimyth -p "local0.info" "[functions/mm_x_stop] Killing mm_sleep_on_ss script..."
        /usr/bin/killall -9 mm_sleep_on_ss
    fi

    if [ -n "`/bin/pidof xscreensaver`" ] ; then
        /usr/bin/logger -t minimyth -p "local0.info" "[functions/mm_x_stop] Killing xscreensaver..."
        /usr/bin/killall xscreensaver
    fi

    if [ -n "`/bin/pidof xscreensaver-command`" ] ; then
        /usr/bin/logger -t minimyth -p "local0.info" "[functions/mm_x_stop] Killing xscreensaver-cammand..."
        /usr/bin/killall xscreensaver-command
    fi

    if [ -n "`/bin/pidof mm_watchdog`" ] ; then
        /usr/bin/logger -t minimyth -p "local0.info" "[functions/mm_x_stop] Killing mm_watchdog script..."
        /usr/bin/killall -9 mm_watchdog
    fi

#    # Exit X applications that are known not to be started by xinit
#    /usr/bin/logger -t minimyth -p "local0.info" "[functions] Exiting all applications..."
#    mm_x_applications_exit ':everything'
#    mm_x_applications_kill ':everything'
#    mm_x_applications_dead ':everything'

    # Return mythfrontend to the main menu
    #/usr/bin/logger -t minimyth -p "local0.info" "[functions/mm_x_stop] Asking MythTV to go to MainMenu..."
    #mm_x_applications_exit 'mythfrontend'

    # Create the list of X applications that may have been started by xinit.
    applications="${applications} ${MM_X_MYTH_PROGRAM}"
    applications="${applications} mythfrontend"
    applications="${applications} mythwelcome"
    applications="${applications} ratpoison"
    applications="${applications} X"
    applications="${applications} x11vnc"
    applications="${applications} xinit"
    applications="${applications} xscreensaver"

    # Create the list of known X applications not keeping X alive, kill them and wait for them to die
    applications=`/bin/echo "${applications}" \
        | /bin/sed -e 's%  *% %g'             \
        | /bin/sed -e 's% %\n%g'              \
        | /usr/bin/sort                       \
        | /usr/bin/uniq                       \
        | /bin/grep -v 'xinit'                \
        | /bin/grep -v 'X'                    \
        | /bin/grep -v "${MM_X_MYTH_PROGRAM}"`
    /usr/bin/logger -t minimyth -p "local0.info" "[functions/mm_x_stop] Exiting apps. not keeping X alive:[${applications}]"
    mm_x_applications_kill ${applications}
    mm_x_applications_dead ${applications}

    # Create the list of xlsclients X applications not keeping X alive, kill them and wait for them to die
    #   All of these should have been killed when we killed the list of known X applications not keeping X alive.
    #   However, there may be some unknown X applications not keeping X alive that we need to kill.
    applications=`/usr/bin/xlsclients -display ':0.0' -a 2> /dev/null \
        | /bin/sed -e 's%  *% %g'                                     \
        | /usr/bin/cut -d ' ' -f 2                                    \
        | /bin/sed -e 's%^.*/%%'                                      \
        | /usr/bin/sort                                               \
        | /usr/bin/uniq                                               \
        | /bin/grep -v 'xinit'                                        \
        | /bin/grep -v 'X'                                            \
        | /bin/grep -v "${MM_X_MYTH_PROGRAM}"`
    /usr/bin/logger -t minimyth -p "local0.info" "[functions/mm_x_stop] Exiting apps. keeing X alive:[${applications}]"
    mm_x_applications_kill ${applications}
    mm_x_applications_dead ${applications}

    # Create the list of the known X application keeping X alive, kill them and wait for them to die.
    applications="${MM_X_MYTH_PROGRAM}"
    mm_x_applications_kill ${applications}
    mm_x_applications_dead ${applications}

    # Create the list of remaining known X applications and wait for them to die.
    /usr/bin/logger -t minimyth -p "local0.info" "[functions/mm_x_stop] Finally stoping X and xinit."
    applications="xinit X"
    mm_x_applications_kill ${applications}

    return 0
}

mm_show_mythnotify() {
    # mm_show_mythnotify <description> <extra> <type> <timeout> <title> <progres_text> <progress>
    # allowable types are"
    # "error"
    # "warning"
    # "ok"
    # "message"     <- this will show message instead notify
    # <image file>  <- this will show <image>
    # ""            <- this will notify without image
    local text="${1}"
    local extra="${2}"
    local type="${3}"
    local message="${1}\n${2}"
    local title=${5}
    local result
    local image
    local progress_text
    local progress
    local timeout=8
    #local send_cmd="/usr/bin/socat STDIN udp4:127.0.0.1:6948"
    local send_cmd="/usr/bin/nc -u -w1 127.0.0.1 6948"

    if [ -n ${4} ] ; then
        timeout=${4}
    fi
    if [ x${title} = 'x' ] ; then
        title="System"
    else
        title=${5}
    fi
    if [ x${6} = 'x' ] ; then
        progress_text=''
    else
        progress_text=${6}
    fi
    if [ x${7} = 'x' ] ; then
        progress=''
    else
        progress=${7}
    fi

    if [ x${type} = "xmessage" ] ; then
        /bin/echo -e "<mythmessage version=\"1\"> <text>${message}</text> <timeout>$timeout</timeout> </mythmessage>" | ${send_cmd}
    else
        if [ x${type} = "xerror" ] ; then
            image="images/mythnotify/error.png"
        elif [ x${type} = "xwarning" ] ; then
            image="images/mythnotify/warning.png"
        elif [ x${type} = "xok" ] ; then
            image="images/mythnotify/check.png"
        elif [ -z ${type} ] ; then
            image=""
        else
            image=${type}
        fi

        /bin/echo -e "
        <mythnotification version=\"1\">
          <image>${image}</image>
          <text>${title}</text>
          <origin></origin>
          <description>${text}</description>
          <extra>${extra}</extra>
          <progress_text>${progress_text}</progress_text>
          <progress>${progress}</progress>
          <timeout>${timeout}</timeout>
        </mythnotification>" | ${send_cmd}
    fi
}

mm_exec_and_notify() {
#  echo -e $1 > /var/tmp/out.tmp 2>&1
#  local title=`cat /var/tmp/out.tmp`
  local title=`echo -e $1.`
  local result=`${2} | sed -e "s/::.*//g"`
  mm_show_mythnotify "${title}" "${result}" "warning"
}

mm_notify_and_exec() {
  local title=`echo -e $1.`
  mm_show_mythnotify "${title}"
  /bin/sleep 5
  local result=`${2} | sed -e "s/::.*//g"`
}

mm_test_master_db_connection() {
    # Function is testing connection with DB at with MM_MASTER_CONNECTION_TEST_TIMEOUT timeout.
    # When MM_MASTER_CONNECTION_TEST_TIMEOUT sec timeout  is reached - functuion will return false
    # inputs: 
    # if non zero input param.if provieded - function will also display msgs on splash screen

    local show_on_splash=$1

    # Test Myth database connection.
    /usr/bin/logger -s -t minimyth -p "local0.info" "[functions/mm_test_db_conn] Testing connection with DB at '${MM_MASTER_SERVER}'"

    i=0
    while [ $i -lt ${MM_MASTER_CONNECTION_TEST_TIMEOUT} ] ; do
        i=$((${i} + 1))
        if ! mm_mythdb_test ; then
            if [ $i -ge ${MM_MASTER_CONNECTION_TEST_TIMEOUT} ] ; then
                /usr/bin/logger -s -t minimyth -p "local0.info" "[functions/mm_test_db_conn] Cannot connect to DB after ${MM_MASTER_CONNECTION_TEST_TIMEOUT}sec."
                if [ -n ${show_on_splash} ] ; then
                    mm_message_output info "Cannot connect to the DB. MythTV will relay on user search from MythTV uPNP discovery ..."
                fi
                /bin/false
                return
            else
                /usr/bin/logger -s -t minimyth -p "local0.info" "[functions/mm_test_db_conn] Trying connect to DB (${i} of ${MM_MASTER_CONNECTION_TEST_TIMEOUT})"
                if [ -n ${show_on_splash} ] ; then
                    mm_message_output info "Awaiting for MythTV master DB avaliability: (${i} of ${MM_MASTER_CONNECTION_TEST_TIMEOUT} seconds) ..."
                fi
                /bin/sleep 1
            fi
        else
            /usr/bin/logger -s -t minimyth -p "local0.info" "[functions/mm_test_db_conn] Connection with DB at \'${MM_MASTER_SERVER}\' is OK. Good!"
            i=${MM_MASTER_CONNECTION_TEST_TIMEOUT}
        fi
    done

    /bin/true
    return

}

myth_start() {

    local mode=$2
    local args="$1"

    /usr/bin/mm_modify_mainmenu & 2> /dev/null

    if [ "x${MM_MYTHTV_RUN_ON_EGLFS}" = "xyes" ] ; then
        export QT_QPA_PLATFORM=eglfs
        export QT_QPA_EGLFS_INTEGRATION=eglfs_kms
        # export QT_QPA_EGLFS_FORCE888=1 # needed only for some platforms
        env
    else
        export QT_QPA_PLATFORM=xcb
    fi

    export QT_PLUGIN_PATH=/usr/lib/qt5/plugins
    export QT_LOGGING_RULES=qt.qpa.*=true
    export __GL_SYNC_TO_VBLANK=1

    if [ -n "${MM_MYTHTV_SET_ENV_VAR}" ] ; then
        export ${MM_MYTHTV_SET_ENV_VAR}
    fi

    env > /var/log/enviroment

    mm_test_master_db_connection

    if [ x${mode} = 'xforeground' ] ; then
        /usr/bin/logger -t minimyth -p "local0.info" "[functions] Starting '${args}' in foreground via X11..."
        su minimyth -c "${args}"
    else
        if [ "x${MM_MYTHTV_RUN_ON_EGLFS}" = "xyes" ] ; then
            /usr/bin/logger -t minimyth -p "local0.info" "[functions] Starting '${args}' in background via EGLFS..."
        else
            /usr/bin/logger -t minimyth -p "local0.info" "[functions] Starting '${args}' in background via X11..."
        fi
        su minimyth -c "${args}" &
    fi

    /bin/true
    return
}

#===============================================================================
# mythfrontend functions.
#===============================================================================
mm_mythfrontend_start() {
    # Called without any param.      : mythfrontend in background on X11 or EGLFS
    # Called with 'foreground' param.: mythfrontend in foreground on X11
    if [ -n "${MM_MYTHFRONTEND_CMDLINE}" ] ; then
        args="${MM_MYTHFRONTEND_CMDLINE} > /var/log/mythfrontend"
    else
        args="/usr/bin/mythfrontend > /var/log/mythfrontend"
    fi
    myth_start "${args}" $1
}

mm_mythwelcome_start() {
    # Called without any param.      : mythfrontend in background on X11 or EGLFS
    # Called with 'foreground' param.: mythfrontend in foreground on X11
    if [ -n "${MM_MYTHFRONTEND_CMDLINE}" ] ; then
        args="${MM_MYTHFRONTEND_CMDLINE} > /var/log/mythfrontend"
    else
        args="/usr/bin/mythwelcome > /var/log/mythfrontend"
    fi
    myth_start "${args}" $1
}



mm_mythfrontend_networkcontrol() {
    local command=$1

    local failed
    local response

    local host
    local port

    failed=1
    response=''

    if [ -n "`/bin/pidof mythfrontend`" ] ; then
        host='localhost'
        port=`mm_mythdb_settings_get NetworkControlPort`

        response=`/bin/echo -e "${command}\nexit" \
                  | /usr/bin/hose ${host} ${port} --out --in \
                    /bin/sh -c "/bin/cat <&3 & \
                                /bin/grep '^#' \
                                | /bin/sed 's%[[:cntrl:]]% %' \
                                | /bin/grep -v '^# *$' \
                                | /bin/sed 's%^#%%' \
                                | /bin/sed 's%  *% %' \
                                | /bin/sed 's%^ %%' \
                                | /bin/sed 's% $%%' >&4" \
                    3<&0 4>&1`
        if [ $? -eq 0 ] ; then
            failed=0
        fi
    fi

    /bin/echo ${response}

    if [ ${failed} -eq 1 ] ; then
        /bin/false
        return
    else
        /bin/true
        return
    fi
}

mm_reload_voip_config() {
    if [ "x${MM_VOIP_ENABLED}" = "xyes" ] ; then
        if [ "x${MM_VOIP_LOAD_CONFIG}" = "xyes" ] ; then
            /bin/rm -f /etc/sip-daemon.conf
            mm_confro_get sip-daemon.conf /etc/sip-daemon.conf
            if [ ! -e /etc/sip-daemon.conf ] ; then
                /usr/bin/logger -s -t minimyth -p "local0.error" \
                    "[functions/mm_reload_voip_config] failed to load sip-daemon.conf file..."
                /bin/false
                return
            fi
        fi
        /bin/rm -f /home/minimyth/.mythtv/phone.xml
        mm_confro_get phone-book.xml /home/minimyth/.mythtv/phone.xml
        if [ ! -e /home/minimyth/.mythtv/phone.xml ] ; then
            /usr/bin/logger -s -t minimyth -p "local0.error" \
                "[functions/mm_reload_voip_config] failed to load phone-book.xml file..."
            /bin/false
            return
        fi
        /usr/bin/logger -s -t minimyth -p "local0.error" \
            "[functions/mm_reload_voip_config] restarting sip-daemon.py..."
        /bin/touch /tmp/exit.sem
        /bin/sleep 3
        /usr/bin/sip-daemon.sh &
    fi

    if [ "x${MM_OPTICAL_RIP_ENABLED}" = "xyes" ] ; then

        /bin/rm -f /home/minimyth/.MakeMKV/settings.conf
        mm_confro_get makemkv.conf /home/minimyth/.MakeMKV/settings.conf
        if [ ! -e /home/minimyth/.MakeMKV/settings.conf ] ; then
            mm_message_output err "error: failed to fetch 'makemkv.conf' file."
            /bin/false
            return
        fi

        /bin/rm -f /usr/bin/makemkvcon
        mm_confro_get makemkvcon /usr/bin/makemkvcon
        /bin/chmod 0755 /usr/bin/makemkvcon
        if [ ! -e /usr/bin/makemkvcon ] ; then
            mm_message_output err "error: failed to fetch 'makemkvcon' binary file."
            /bin/false
            return
        fi
    fi

    /bin/true
}

mm_redownload_theme() {
    # Re-mount MythTV theme directory.
    if [ -n "${MM_THEME_URL}" ] ; then
        /usr/bin/logger -s -t minimyth -p "local0.info" "[functions/mm_redownload_theme] Un-mounting theme from ${MM_THEME_URL}"
        if ! mm_url_umount "${MM_THEME_URL}" "/usr/share/mythtv/themes/${MM_THEME_NAME}" ; then
            /usr/bin/logger -s -t minimyth -p "local0.info" "[functions/mm_redownload_theme] Can't umount theme from ${MM_THEME_URL}"
            /bin/false
            return
        fi
        /bin/sleep 3
        /usr/bin/logger -s -t minimyth -p "local0.info" "[functions/mm_redownload_theme] Re-mounting theme from ${MM_THEME_URL}"
        if ! mm_url_mount "${MM_THEME_URL}" "/usr/share/mythtv/themes/${MM_THEME_NAME}" ; then
            /usr/bin/logger -s -t minimyth -p "local0.info" "[functions/mm_redownload_theme] Can't download/re-mount theme from ${MM_THEME_URL}. Fallback to build-in MythCenter-wide..."
            mm_mythdb_settings_set "Theme" "MythCenter-wide"
            /bin/false
            return
        else
            /usr/bin/logger -s -t minimyth -p "local0.info" "[functions/mm_redownload_theme] Theme from ${MM_THEME_URL} successfuly mounted..."
            mm_mythdb_settings_set "Theme" "${MM_THEME_NAME}"
        fi
    fi
    # Re-mount MythTV thememenu directory.
    if [ -n "${MM_THEMEMENU_URL}" ] ; then
        /usr/bin/logger -s -t minimyth -p "local0.info" "[functions/mm_redownload_theme] Un-mounting thememenu from ${MM_THEMEMENU_URL}"
        if ! mm_url_umount "${MM_THEMEMENU_URL}" "/usr/share/mythtv/themes/${MM_THEMEMENU_NAME}" ; then
            /usr/bin/logger -s -t minimyth -p "local0.info" "[functions/mm_redownload_theme] Can't umount thememenu from ${MM_THEMEMENU_URL}"
            /bin/false
            return
        fi
        /bin/sleep 3
        /usr/bin/logger -s -t minimyth -p "local0.info" "[functions/mm_redownload_theme] Re-mounting thememenu from ${MM_THEMEMENU_URL}"
        if ! mm_url_mount "${MM_THEMEMENU_URL}" "/usr/share/mythtv/themes/${MM_THEMEMENU_NAME}" ; then
            /usr/bin/logger -s -t minimyth -p "local0.info" "[functions/mm_redownload_theme] Can't download/re-mount thememenu from ${MM_THEMEMENU_URL}"
            /bin/false
            return
        fi
    fi
    return
}


#-----------------Functions to support devel-* scripts---------------------------------------------------

devel_find_files() {
    # Builds and returns space separated list of files conforming name patterns within given dir
    # If 3rd param is 'remote' - function will use ssh to find files at remote location
    # arg1: <dir path>
    # arg2: <filename1* filename2* ...>
    # arg3: 'remote'
    # ret: <path/filename1.x.z filename2*.a.b>

    local path=$1
    local files_list=$2
    local remote=$3
    local files_found

    for file in ${files_list}; do

        if [ x${remote} = "xremote" ];then

            f=`ssh -c none ${devel_login} "find ${path} -type f -name ${file}"`

        else

            f=`find ${path} -type f -name ${file}`

        fi

        files_found=${files_found}" "${f}

    done

    echo ${files_found}
}

devel_list_files() {
    # List files
    # arg1: <path/file1..."

    local files_list=$1

    for file in ${files_list}; do

            echo "    "${file}

    done

}

devel_install_files() {

    local src_path=$1
    local dst_path=$2
    local files_list=$3

    files_to_uninstall=$(devel_find_files ${dst_path} "${files_list}")

    if [ -z "${files_to_uninstall}" ]; then

        echo " "
        echo "WARNING: no ANY files found to uninstall!!!"
        echo " "

    else
        echo "==> Old files to uninstall from: [${dst_path}]"
        echo " "

        devel_list_files "${files_to_uninstall}"

        echo " "
    fi

    files_to_install=$(devel_find_files "${src_path}" "${files_list}" remote)

    if [ -z "${files_to_install}" ]; then

        echo " "
        echo "WARNING: no ANY files found to install!!!"
        echo " "
        echo "Script will now exit..."
        echo " "
        exit 1

    else

        echo "==> New files to install from remote: [${src_path}]"
        echo " "

        devel_list_files "${files_to_install}"

        echo " "

    fi

    echo "==> Uninstalling files..."
    echo " "

    for file in ${files_to_uninstall}; do

        if [ x${dry_run} = "xtrue" ]; then

            echo "    dry run: [rm -fv" ${file}"]"

        else

            rm -fv ${file}

        fi

    done

    echo " "
    echo "==> Installing files..."
    echo " "

    for file in ${files_to_install}; do

        dst_file=`echo "${file}" | sed "s%${src_path}%${dst_path}%"`

        if [ x${dry_run} = "xtrue" ]; then


            echo "    dry run: [scp -c none "${devel_login}":"${file} ${dst_file}"]"
            echo "             [chown root:root "${dst_file}"]"
            echo "             [chmod 0755 "${dst_file}"]"

        else

            scp -c none ${devel_login}:${file} ${dst_file}

            chown root:root ${dst_file}
            chmod 0755 ${dst_file}

        fi

    done

    echo " "

}
